Use single quotes :P
This commit is contained in:
parent
ada37035cd
commit
19b2e5574b
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"singleQuote": false
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
const crypto = require("crypto");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const crypto = require('crypto');
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const db = require("./utils/data");
|
||||
const secretKey = require("./secretKey");
|
||||
const db = require('./utils/data');
|
||||
const secretKey = require('./secretKey');
|
||||
|
||||
function getCurrentSeconds() {
|
||||
return Math.floor(Date.now() / 1000);
|
||||
}
|
||||
|
||||
function createTokenId() {
|
||||
return crypto.randomBytes(16).toString("hex");
|
||||
return crypto.randomBytes(16).toString('hex');
|
||||
}
|
||||
|
||||
function createToken(scopes = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const payload = {
|
||||
jti: createTokenId(),
|
||||
iss: "https://unpkg.com",
|
||||
iss: 'https://unpkg.com',
|
||||
iat: getCurrentSeconds(),
|
||||
scopes
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ function createToken(scopes = {}) {
|
|||
jwt.sign(
|
||||
payload,
|
||||
secretKey.private,
|
||||
{ algorithm: "RS256" },
|
||||
{ algorithm: 'RS256' },
|
||||
(error, token) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
|
@ -36,11 +36,11 @@ function createToken(scopes = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
const revokedTokensSet = "revoked-tokens";
|
||||
const revokedTokensSet = 'revoked-tokens';
|
||||
|
||||
function verifyToken(token) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const options = { algorithms: ["RS256"] };
|
||||
const options = { algorithms: ['RS256'] };
|
||||
|
||||
jwt.verify(token, secretKey.public, options, (error, payload) => {
|
||||
if (error) {
|
||||
|
|
|
@ -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) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
require("isomorphic-fetch");
|
||||
const invariant = require("invariant");
|
||||
const gunzip = require("gunzip-maybe");
|
||||
const ndjson = require("ndjson");
|
||||
require('isomorphic-fetch');
|
||||
const invariant = require('invariant');
|
||||
const gunzip = require('gunzip-maybe');
|
||||
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 cloudflareKey = process.env.CLOUDFLARE_KEY;
|
||||
|
||||
invariant(
|
||||
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) {
|
||||
return fetch(`${cloudflareURL}${path}`, {
|
||||
headers: Object.assign({}, headers, {
|
||||
"X-Auth-Email": cloudflareEmail,
|
||||
"X-Auth-Key": cloudflareKey
|
||||
'X-Auth-Email': cloudflareEmail,
|
||||
'X-Auth-Key': cloudflareKey
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ function getJSON(path, headers) {
|
|||
if (!data.success) {
|
||||
console.error(`CloudflareAPI.getJSON failed at ${path}`);
|
||||
console.error(data);
|
||||
throw new Error("Failed to getJSON from Cloudflare");
|
||||
throw new Error('Failed to getJSON from Cloudflare');
|
||||
}
|
||||
|
||||
return data.result;
|
||||
|
@ -51,9 +51,9 @@ function reduceResults(target, values) {
|
|||
Object.keys(values).forEach(key => {
|
||||
const value = values[key];
|
||||
|
||||
if (typeof value === "object" && value) {
|
||||
if (typeof value === 'object' && value) {
|
||||
target[key] = reduceResults(target[key] || {}, value);
|
||||
} else if (typeof value === "number") {
|
||||
} else if (typeof value === 'number') {
|
||||
target[key] = (target[key] || 0) + values[key];
|
||||
}
|
||||
});
|
||||
|
@ -75,7 +75,7 @@ function getZoneAnalyticsDashboard(zones, since, until) {
|
|||
|
||||
function getJSONStream(path, headers) {
|
||||
const gzipHeaders = Object.assign({}, headers, {
|
||||
"Accept-Encoding": "gzip"
|
||||
'Accept-Encoding': 'gzip'
|
||||
});
|
||||
|
||||
return get(path, gzipHeaders)
|
||||
|
@ -84,7 +84,7 @@ function getJSONStream(path, headers) {
|
|||
}
|
||||
|
||||
function getLogs(zoneId, startTime, endTime, fieldsArray) {
|
||||
const fields = fieldsArray.join(",");
|
||||
const fields = fieldsArray.join(',');
|
||||
|
||||
// console.log(
|
||||
// `https://api.cloudflare.com/client/v4/zones/${zoneId}/logs/received?start=${startTime}&end=${endTime}&fields=${fields}`
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const db = require("./utils/data");
|
||||
const db = require('./utils/data');
|
||||
|
||||
const CloudflareAPI = require("./CloudflareAPI");
|
||||
const BlacklistAPI = require("./BlacklistAPI");
|
||||
const CloudflareAPI = require('./CloudflareAPI');
|
||||
const BlacklistAPI = require('./BlacklistAPI');
|
||||
|
||||
function prunePackages(packagesMap) {
|
||||
return Promise.all(
|
||||
|
@ -39,7 +39,7 @@ function createScoresMap(array) {
|
|||
|
||||
function getScoresMap(key, n = 100) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.zrevrange(key, 0, n, "withscores", (error, value) => {
|
||||
db.zrevrange(key, 0, n, 'withscores', (error, value) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
|
@ -141,7 +141,7 @@ function extractPublicInfo(data) {
|
|||
};
|
||||
}
|
||||
|
||||
const DomainNames = ["unpkg.com", "npmcdn.com"];
|
||||
const DomainNames = ['unpkg.com', 'npmcdn.com'];
|
||||
|
||||
function fetchStats(since, until) {
|
||||
return CloudflareAPI.getZones(DomainNames).then(zones => {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const AuthAPI = require("../AuthAPI");
|
||||
const AuthAPI = require('../AuthAPI');
|
||||
|
||||
describe("Auth API", () => {
|
||||
describe('Auth API', () => {
|
||||
beforeEach(done => {
|
||||
AuthAPI.removeAllRevokedTokens().then(() => done(), done);
|
||||
});
|
||||
|
||||
it("creates tokens with the right scopes", done => {
|
||||
it('creates tokens with the right scopes', done => {
|
||||
const scopes = {
|
||||
blacklist: {
|
||||
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 = {};
|
||||
|
||||
AuthAPI.createToken(scopes).then(token => {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const BlacklistAPI = require("../BlacklistAPI");
|
||||
const BlacklistAPI = require('../BlacklistAPI');
|
||||
|
||||
describe("Blacklist API", () => {
|
||||
describe('Blacklist API', () => {
|
||||
beforeEach(done => {
|
||||
BlacklistAPI.removeAllPackages().then(() => done(), done);
|
||||
});
|
||||
|
||||
it("adds and removes packages to/from the blacklist", done => {
|
||||
const packageName = "bad-package";
|
||||
it('adds and removes packages to/from the blacklist', done => {
|
||||
const packageName = 'bad-package';
|
||||
|
||||
BlacklistAPI.addPackage(packageName).then(() => {
|
||||
BlacklistAPI.getPackages().then(packageNames => {
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
const request = require("supertest");
|
||||
const request = require('supertest');
|
||||
|
||||
const createServer = require("../createServer");
|
||||
const withRevokedToken = require("./utils/withRevokedToken");
|
||||
const withToken = require("./utils/withToken");
|
||||
const createServer = require('../createServer');
|
||||
const withRevokedToken = require('./utils/withRevokedToken');
|
||||
const withToken = require('./utils/withToken');
|
||||
|
||||
describe("The /_auth endpoint", () => {
|
||||
describe('The /_auth endpoint', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("POST /_auth", () => {
|
||||
it("creates a new auth token", done => {
|
||||
describe('POST /_auth', () => {
|
||||
it('creates a new auth token', done => {
|
||||
request(server)
|
||||
.post("/_auth")
|
||||
.post('/_auth')
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("token");
|
||||
expect(res.body).toHaveProperty('token');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /_auth", () => {
|
||||
describe("with no auth", () => {
|
||||
it("echoes back null", done => {
|
||||
describe('GET /_auth', () => {
|
||||
describe('with no auth', () => {
|
||||
it('echoes back null', done => {
|
||||
request(server)
|
||||
.get("/_auth")
|
||||
.get('/_auth')
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBe(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a revoked auth token", () => {
|
||||
it("echoes back null", done => {
|
||||
describe('with a revoked auth token', () => {
|
||||
it('echoes back null', done => {
|
||||
withRevokedToken({ some: { scope: true } }, token => {
|
||||
request(server)
|
||||
.get("/_auth?token=" + token)
|
||||
.get('/_auth?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBe(null);
|
||||
done();
|
||||
});
|
||||
|
@ -48,14 +48,14 @@ describe("The /_auth endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("with a valid auth token", () => {
|
||||
it("echoes back the auth payload", done => {
|
||||
describe('with a valid auth token', () => {
|
||||
it('echoes back the auth payload', done => {
|
||||
withToken({ some: { scope: true } }, token => {
|
||||
request(server)
|
||||
.get("/_auth?token=" + token)
|
||||
.get('/_auth?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(typeof res.body.auth).toBe("object");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(typeof res.body.auth).toBe('object');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
const request = require("supertest");
|
||||
const request = require('supertest');
|
||||
|
||||
const createServer = require("../createServer");
|
||||
const clearBlacklist = require("./utils/clearBlacklist");
|
||||
const withToken = require("./utils/withToken");
|
||||
const createServer = require('../createServer');
|
||||
const clearBlacklist = require('./utils/clearBlacklist');
|
||||
const withToken = require('./utils/withToken');
|
||||
|
||||
describe("The /_blacklist endpoint", () => {
|
||||
describe('The /_blacklist endpoint', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("POST /_blacklist", () => {
|
||||
describe('POST /_blacklist', () => {
|
||||
afterEach(clearBlacklist);
|
||||
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.post("/_blacklist")
|
||||
.post('/_blacklist')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -25,11 +25,11 @@ describe("The /_blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
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 => {
|
||||
request(server)
|
||||
.post("/_blacklist")
|
||||
.send({ token, packageName: "bad-package" })
|
||||
.post('/_blacklist')
|
||||
.send({ token, packageName: 'bad-package' })
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.ok).toBe(true);
|
||||
|
@ -40,11 +40,11 @@ describe("The /_blacklist endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("GET /_blacklist", () => {
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('GET /_blacklist', () => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.get("/_blacklist")
|
||||
.get('/_blacklist')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -53,10 +53,10 @@ describe("The /_blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
describe('with the "blacklist.read" scope', () => {
|
||||
it("can read the blacklist", done => {
|
||||
it('can read the blacklist', done => {
|
||||
withToken({ blacklist: { read: true } }, token => {
|
||||
request(server)
|
||||
.get("/_blacklist?token=" + token)
|
||||
.get('/_blacklist?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
done();
|
||||
|
@ -66,11 +66,11 @@ describe("The /_blacklist endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("DELETE /_blacklist/:packageName", () => {
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('DELETE /_blacklist/:packageName', () => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.delete("/_blacklist/bad-package")
|
||||
.delete('/_blacklist/bad-package')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -79,10 +79,10 @@ describe("The /_blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
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 => {
|
||||
request(server)
|
||||
.delete("/_blacklist/bad-package")
|
||||
.delete('/_blacklist/bad-package')
|
||||
.send({ token })
|
||||
.end((err, res) => {
|
||||
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 => {
|
||||
request(server)
|
||||
.delete("/_blacklist/@scope/bad-package")
|
||||
.delete('/_blacklist/@scope/bad-package')
|
||||
.send({ token })
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
|
|
|
@ -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;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("GET /_publicKey", () => {
|
||||
it("echoes the public key", done => {
|
||||
describe('GET /_publicKey', () => {
|
||||
it('echoes the public key', done => {
|
||||
request(server)
|
||||
.get("/_publicKey")
|
||||
.get('/_publicKey')
|
||||
.end((err, res) => {
|
||||
expect(res.text).toMatch(/PUBLIC KEY/);
|
||||
done();
|
||||
|
|
|
@ -1,47 +1,47 @@
|
|||
const request = require("supertest");
|
||||
const request = require('supertest');
|
||||
|
||||
const createServer = require("../createServer");
|
||||
const withAuthHeader = require("./utils/withAuthHeader");
|
||||
const withRevokedToken = require("./utils/withRevokedToken");
|
||||
const withToken = require("./utils/withToken");
|
||||
const createServer = require('../createServer');
|
||||
const withAuthHeader = require('./utils/withAuthHeader');
|
||||
const withRevokedToken = require('./utils/withRevokedToken');
|
||||
const withToken = require('./utils/withToken');
|
||||
|
||||
describe("The /api/auth endpoint", () => {
|
||||
describe('The /api/auth endpoint', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("POST /api/auth", () => {
|
||||
it("creates a new auth token", done => {
|
||||
describe('POST /api/auth', () => {
|
||||
it('creates a new auth token', done => {
|
||||
request(server)
|
||||
.post("/api/auth")
|
||||
.post('/api/auth')
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("token");
|
||||
expect(res.body).toHaveProperty('token');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /api/auth", () => {
|
||||
describe("with no auth", () => {
|
||||
it("echoes back null", done => {
|
||||
describe('GET /api/auth', () => {
|
||||
describe('with no auth', () => {
|
||||
it('echoes back null', done => {
|
||||
request(server)
|
||||
.get("/api/auth")
|
||||
.get('/api/auth')
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBe(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with a revoked auth token", () => {
|
||||
it("echoes back null", done => {
|
||||
describe('with a revoked auth token', () => {
|
||||
it('echoes back null', done => {
|
||||
withRevokedToken({ some: { scope: true } }, token => {
|
||||
request(server)
|
||||
.get("/api/auth?token=" + token)
|
||||
.get('/api/auth?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBe(null);
|
||||
done();
|
||||
});
|
||||
|
@ -49,16 +49,16 @@ describe("The /api/auth endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("with a valid auth token", () => {
|
||||
describe("in the query string", () => {
|
||||
it("echoes back the auth payload", done => {
|
||||
describe('with a valid auth token', () => {
|
||||
describe('in the query string', () => {
|
||||
it('echoes back the auth payload', done => {
|
||||
const scopes = { some: { scope: true } };
|
||||
|
||||
withToken(scopes, token => {
|
||||
request(server)
|
||||
.get("/api/auth?token=" + token)
|
||||
.get('/api/auth?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBeDefined();
|
||||
expect(res.body.auth.scopes).toMatchObject(scopes);
|
||||
done();
|
||||
|
@ -67,16 +67,16 @@ describe("The /api/auth endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("in the Authorization header", () => {
|
||||
it("echoes back the auth payload", done => {
|
||||
describe('in the Authorization header', () => {
|
||||
it('echoes back the auth payload', done => {
|
||||
const scopes = { some: { scope: true } };
|
||||
|
||||
withAuthHeader(scopes, header => {
|
||||
request(server)
|
||||
.get("/api/auth")
|
||||
.get('/api/auth')
|
||||
.set({ Authorization: header })
|
||||
.end((err, res) => {
|
||||
expect(res.body).toHaveProperty("auth");
|
||||
expect(res.body).toHaveProperty('auth');
|
||||
expect(res.body.auth).toBeDefined();
|
||||
expect(res.body.auth.scopes).toMatchObject(scopes);
|
||||
done();
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
const request = require("supertest");
|
||||
const request = require('supertest');
|
||||
|
||||
const createServer = require("../createServer");
|
||||
const clearBlacklist = require("./utils/clearBlacklist");
|
||||
const withToken = require("./utils/withToken");
|
||||
const createServer = require('../createServer');
|
||||
const clearBlacklist = require('./utils/clearBlacklist');
|
||||
const withToken = require('./utils/withToken');
|
||||
|
||||
describe("The /api/blacklist endpoint", () => {
|
||||
describe('The /api/blacklist endpoint', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("POST /api/blacklist", () => {
|
||||
describe('POST /api/blacklist', () => {
|
||||
afterEach(clearBlacklist);
|
||||
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.post("/api/blacklist")
|
||||
.post('/api/blacklist')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -25,11 +25,11 @@ describe("The /api/blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
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 => {
|
||||
request(server)
|
||||
.post("/api/blacklist")
|
||||
.send({ token, packageName: "bad-package" })
|
||||
.post('/api/blacklist')
|
||||
.send({ token, packageName: 'bad-package' })
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.ok).toBe(true);
|
||||
|
@ -40,11 +40,11 @@ describe("The /api/blacklist endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("GET /api/blacklist", () => {
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('GET /api/blacklist', () => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.get("/api/blacklist")
|
||||
.get('/api/blacklist')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -53,10 +53,10 @@ describe("The /api/blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
describe('with the "blacklist.read" scope', () => {
|
||||
it("can read the blacklist", done => {
|
||||
it('can read the blacklist', done => {
|
||||
withToken({ blacklist: { read: true } }, token => {
|
||||
request(server)
|
||||
.get("/api/blacklist?token=" + token)
|
||||
.get('/api/blacklist?token=' + token)
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
done();
|
||||
|
@ -66,11 +66,11 @@ describe("The /api/blacklist endpoint", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("DELETE /api/blacklist", () => {
|
||||
describe("with no auth", () => {
|
||||
it("is forbidden", done => {
|
||||
describe('DELETE /api/blacklist', () => {
|
||||
describe('with no auth', () => {
|
||||
it('is forbidden', done => {
|
||||
request(server)
|
||||
.delete("/api/blacklist")
|
||||
.delete('/api/blacklist')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
@ -79,11 +79,11 @@ describe("The /api/blacklist endpoint", () => {
|
|||
});
|
||||
|
||||
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 => {
|
||||
request(server)
|
||||
.delete("/api/blacklist")
|
||||
.send({ token, packageName: "bad-package" })
|
||||
.delete('/api/blacklist')
|
||||
.send({ token, packageName: 'bad-package' })
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
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 => {
|
||||
request(server)
|
||||
.delete("/api/blacklist")
|
||||
.send({ token, packageName: "@scope/bad-package" })
|
||||
.delete('/api/blacklist')
|
||||
.send({ token, packageName: '@scope/bad-package' })
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.ok).toBe(true);
|
||||
|
|
|
@ -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;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
describe("GET /api/publicKey", () => {
|
||||
it("echoes the public key", done => {
|
||||
describe('GET /api/publicKey', () => {
|
||||
it('echoes the public key', done => {
|
||||
request(server)
|
||||
.get("/api/publicKey")
|
||||
.get('/api/publicKey')
|
||||
.end((err, res) => {
|
||||
expect(res.text).toMatch(/PUBLIC KEY/);
|
||||
done();
|
||||
|
|
|
@ -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 withBlacklist = require("./utils/withBlacklist");
|
||||
const clearBlacklist = require('./utils/clearBlacklist');
|
||||
const withBlacklist = require('./utils/withBlacklist');
|
||||
|
||||
describe("The server", () => {
|
||||
describe('The server', () => {
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
server = createServer();
|
||||
});
|
||||
|
||||
it("redirects /_meta to ?meta", done => {
|
||||
it('redirects /_meta to ?meta', done => {
|
||||
request(server)
|
||||
.get("/_meta/react")
|
||||
.get('/_meta/react')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(301);
|
||||
expect(res.headers.location).toBe("/react?meta");
|
||||
expect(res.headers.location).toBe('/react?meta');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("redirects ?json to ?meta", done => {
|
||||
it('redirects ?json to ?meta', done => {
|
||||
request(server)
|
||||
.get("/react?json")
|
||||
.get('/react?json')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(301);
|
||||
expect(res.headers.location).toBe("/react?meta");
|
||||
expect(res.headers.location).toBe('/react?meta');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("redirects invalid query params", done => {
|
||||
it('redirects invalid query params', done => {
|
||||
request(server)
|
||||
.get("/react?main=index&invalid")
|
||||
.get('/react?main=index&invalid')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(302);
|
||||
expect(res.headers.location).toBe("/react?main=index");
|
||||
expect(res.headers.location).toBe('/react?main=index');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects invalid package names", done => {
|
||||
it('rejects invalid package names', done => {
|
||||
request(server)
|
||||
.get("/_invalid/index.js")
|
||||
.get('/_invalid/index.js')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("blacklisted packages", () => {
|
||||
describe('blacklisted packages', () => {
|
||||
afterEach(clearBlacklist);
|
||||
|
||||
it("does not serve blacklisted packages", done => {
|
||||
withBlacklist(["bad-package"], () => {
|
||||
it('does not serve blacklisted packages', done => {
|
||||
withBlacklist(['bad-package'], () => {
|
||||
request(server)
|
||||
.get("/bad-package/index.js")
|
||||
.get('/bad-package/index.js')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(403);
|
||||
done();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
const closeDatabase = require("./utils/closeDatabase");
|
||||
const closeDatabase = require('./utils/closeDatabase');
|
||||
|
||||
afterAll(closeDatabase);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const BlacklistAPI = require("../../BlacklistAPI");
|
||||
const BlacklistAPI = require('../../BlacklistAPI');
|
||||
|
||||
function clearBlacklist(done) {
|
||||
BlacklistAPI.removeAllPackages().then(done, done);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const withToken = require("./withToken");
|
||||
const withToken = require('./withToken');
|
||||
|
||||
function encodeBase64(token) {
|
||||
return Buffer.from(token).toString("base64");
|
||||
return Buffer.from(token).toString('base64');
|
||||
}
|
||||
|
||||
function withAuthHeader(scopes, done) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const BlacklistAPI = require("../../BlacklistAPI");
|
||||
const BlacklistAPI = require('../../BlacklistAPI');
|
||||
|
||||
function withBlacklist(blacklist, done) {
|
||||
Promise.all(blacklist.map(BlacklistAPI.addPackage)).then(done);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const withToken = require("./withToken");
|
||||
const AuthAPI = require("../../AuthAPI");
|
||||
const withToken = require('./withToken');
|
||||
const AuthAPI = require('../../AuthAPI');
|
||||
|
||||
function withRevokedToken(scopes, done) {
|
||||
withToken(scopes, token => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const AuthAPI = require("../../AuthAPI");
|
||||
const AuthAPI = require('../../AuthAPI');
|
||||
|
||||
function withToken(scopes, done) {
|
||||
AuthAPI.createToken(scopes).then(done);
|
||||
|
|
|
@ -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) {
|
||||
const packageName = req.body.packageName;
|
||||
|
@ -15,7 +15,7 @@ function addToBlacklist(req, res) {
|
|||
|
||||
// Disallow invalid package names.
|
||||
if (nameErrors) {
|
||||
const reason = nameErrors.join(", ");
|
||||
const reason = nameErrors.join(', ');
|
||||
return res.status(403).send({
|
||||
error: `Invalid package name "${packageName}" (${reason})`
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ function addToBlacklist(req, res) {
|
|||
res.send({
|
||||
ok: true,
|
||||
message: `Package "${packageName}" was ${
|
||||
added ? "added to" : "already in"
|
||||
added ? 'added to' : 'already in'
|
||||
} the blacklist`
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const AuthAPI = require("../AuthAPI");
|
||||
const AuthAPI = require('../AuthAPI');
|
||||
|
||||
const defaultScopes = {
|
||||
blacklist: {
|
||||
|
@ -15,7 +15,7 @@ function createAuth(req, res) {
|
|||
console.error(error);
|
||||
|
||||
res.status(500).send({
|
||||
error: "Unable to generate auth token"
|
||||
error: 'Unable to generate auth token'
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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) {
|
||||
// TODO: Remove req.packageName when DELETE
|
||||
|
@ -17,7 +17,7 @@ function removeFromBlacklist(req, res) {
|
|||
|
||||
// Disallow invalid package names.
|
||||
if (nameErrors) {
|
||||
const reason = nameErrors.join(", ");
|
||||
const reason = nameErrors.join(', ');
|
||||
return res.status(403).send({
|
||||
error: `Invalid package name "${packageName}" (${reason})`
|
||||
});
|
||||
|
@ -35,7 +35,7 @@ function removeFromBlacklist(req, res) {
|
|||
res.send({
|
||||
ok: true,
|
||||
message: `Package "${packageName}" was ${
|
||||
removed ? "removed from" : "not in"
|
||||
removed ? 'removed from' : 'not in'
|
||||
} the blacklist`
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
const React = require("react");
|
||||
const ReactDOMServer = require("react-dom/server");
|
||||
const semver = require("semver");
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
const semver = require('semver');
|
||||
|
||||
const MainPage = require("../client/MainPage");
|
||||
const AutoIndexApp = require("../client/autoIndex/App");
|
||||
const createHTML = require("../client/utils/createHTML");
|
||||
const renderPage = require("../utils/renderPage");
|
||||
const MainPage = require('../client/MainPage');
|
||||
const AutoIndexApp = require('../client/autoIndex/App');
|
||||
const createHTML = require('../client/utils/createHTML');
|
||||
const renderPage = require('../utils/renderPage');
|
||||
|
||||
const globalScripts =
|
||||
process.env.NODE_ENV === "production"
|
||||
process.env.NODE_ENV === 'production'
|
||||
? [
|
||||
"/react@16.4.1/umd/react.production.min.js",
|
||||
"/react-dom@16.4.1/umd/react-dom.production.min.js"
|
||||
'/react@16.4.1/umd/react.production.min.js',
|
||||
'/react-dom@16.4.1/umd/react-dom.production.min.js'
|
||||
]
|
||||
: [
|
||||
"/react@16.4.1/umd/react.development.js",
|
||||
"/react-dom@16.4.1/umd/react-dom.development.js"
|
||||
'/react@16.4.1/umd/react.development.js',
|
||||
'/react-dom@16.4.1/umd/react-dom.development.js'
|
||||
];
|
||||
|
||||
function byVersion(a, b) {
|
||||
|
@ -23,8 +23,8 @@ function byVersion(a, b) {
|
|||
}
|
||||
|
||||
function serveAutoIndexPage(req, res) {
|
||||
const scripts = globalScripts.concat(req.assets.getScripts("autoIndex"));
|
||||
const styles = req.assets.getStyles("autoIndex");
|
||||
const scripts = globalScripts.concat(req.assets.getScripts('autoIndex'));
|
||||
const styles = req.assets.getStyles('autoIndex');
|
||||
|
||||
const props = {
|
||||
packageName: req.packageName,
|
||||
|
@ -49,8 +49,8 @@ function serveAutoIndexPage(req, res) {
|
|||
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public,max-age=60", // 1 minute
|
||||
"Cache-Tag": "auto-index"
|
||||
'Cache-Control': 'public,max-age=60', // 1 minute
|
||||
'Cache-Tag': 'auto-index'
|
||||
})
|
||||
.send(html);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const serveAutoIndexPage = require("./serveAutoIndexPage");
|
||||
const serveHTMLModule = require("./serveHTMLModule");
|
||||
const serveJavaScriptModule = require("./serveJavaScriptModule");
|
||||
const serveStaticFile = require("./serveStaticFile");
|
||||
const serveMetadata = require("./serveMetadata");
|
||||
const serveAutoIndexPage = require('./serveAutoIndexPage');
|
||||
const serveHTMLModule = require('./serveHTMLModule');
|
||||
const serveJavaScriptModule = require('./serveJavaScriptModule');
|
||||
const serveStaticFile = require('./serveStaticFile');
|
||||
const serveMetadata = require('./serveMetadata');
|
||||
|
||||
/**
|
||||
* Send the file, JSON metadata, or HTML directory listing.
|
||||
|
@ -12,23 +12,23 @@ function serveFile(req, res) {
|
|||
return serveMetadata(req, res);
|
||||
}
|
||||
|
||||
if (req.entry.type === "directory") {
|
||||
if (req.entry.type === 'directory') {
|
||||
return serveAutoIndexPage(req, res);
|
||||
}
|
||||
|
||||
if (req.query.module != null) {
|
||||
if (req.entry.contentType === "application/javascript") {
|
||||
if (req.entry.contentType === 'application/javascript') {
|
||||
return serveJavaScriptModule(req, res);
|
||||
}
|
||||
|
||||
if (req.entry.contentType === "text/html") {
|
||||
if (req.entry.contentType === 'text/html') {
|
||||
return serveHTMLModule(req, res);
|
||||
}
|
||||
|
||||
return res
|
||||
.status(403)
|
||||
.type("text")
|
||||
.send("?module mode is available only for JavaScript and HTML files");
|
||||
.type('text')
|
||||
.send('?module mode is available only for JavaScript and HTML files');
|
||||
}
|
||||
|
||||
serveStaticFile(req, res);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
const etag = require("etag");
|
||||
const cheerio = require("cheerio");
|
||||
const etag = require('etag');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const getContentTypeHeader = require("../utils/getContentTypeHeader");
|
||||
const rewriteBareModuleIdentifiers = require("../utils/rewriteBareModuleIdentifiers");
|
||||
const getContentTypeHeader = require('../utils/getContentTypeHeader');
|
||||
const rewriteBareModuleIdentifiers = require('../utils/rewriteBareModuleIdentifiers');
|
||||
|
||||
function serveHTMLModule(req, res) {
|
||||
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(
|
||||
rewriteBareModuleIdentifiers($(element).html(), req.packageConfig)
|
||||
);
|
||||
|
@ -18,11 +18,11 @@ function serveHTMLModule(req, res) {
|
|||
|
||||
res
|
||||
.set({
|
||||
"Content-Length": Buffer.byteLength(code),
|
||||
"Content-Type": getContentTypeHeader(req.entry.contentType),
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
'Content-Length': Buffer.byteLength(code),
|
||||
'Content-Type': getContentTypeHeader(req.entry.contentType),
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
ETag: etag(code),
|
||||
"Cache-Tag": "file, html-file, html-module"
|
||||
'Cache-Tag': 'file, html-file, html-module'
|
||||
})
|
||||
.send(code);
|
||||
} catch (error) {
|
||||
|
@ -38,7 +38,7 @@ function serveHTMLModule(req, res) {
|
|||
|
||||
res
|
||||
.status(500)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(
|
||||
`Cannot generate module for ${req.packageSpec}${
|
||||
req.filename
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
const etag = require("etag");
|
||||
const etag = require('etag');
|
||||
|
||||
const getContentTypeHeader = require("../utils/getContentTypeHeader");
|
||||
const rewriteBareModuleIdentifiers = require("../utils/rewriteBareModuleIdentifiers");
|
||||
const getContentTypeHeader = require('../utils/getContentTypeHeader');
|
||||
const rewriteBareModuleIdentifiers = require('../utils/rewriteBareModuleIdentifiers');
|
||||
|
||||
function serveJavaScriptModule(req, res) {
|
||||
try {
|
||||
const code = rewriteBareModuleIdentifiers(
|
||||
req.entry.content.toString("utf8"),
|
||||
req.entry.content.toString('utf8'),
|
||||
req.packageConfig
|
||||
);
|
||||
|
||||
res
|
||||
.set({
|
||||
"Content-Length": Buffer.byteLength(code),
|
||||
"Content-Type": getContentTypeHeader(req.entry.contentType),
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
'Content-Length': Buffer.byteLength(code),
|
||||
'Content-Type': getContentTypeHeader(req.entry.contentType),
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
ETag: etag(code),
|
||||
"Cache-Tag": "file,js-file,js-module"
|
||||
'Cache-Tag': 'file,js-file,js-module'
|
||||
})
|
||||
.send(code);
|
||||
} catch (error) {
|
||||
|
@ -32,7 +32,7 @@ function serveJavaScriptModule(req, res) {
|
|||
|
||||
res
|
||||
.status(500)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(
|
||||
`Cannot generate module for ${req.packageSpec}${
|
||||
req.filename
|
||||
|
|
|
@ -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) {
|
||||
const dirname = entry.name || ".";
|
||||
const dirname = entry.name || '.';
|
||||
|
||||
return Object.keys(entries)
|
||||
.filter(name => entry.name !== name && path.dirname(name) === dirname)
|
||||
|
@ -16,12 +16,12 @@ function getMetadata(entry, entries) {
|
|||
type: entry.type
|
||||
};
|
||||
|
||||
if (entry.type === "file") {
|
||||
if (entry.type === 'file') {
|
||||
metadata.contentType = entry.contentType;
|
||||
metadata.integrity = entry.integrity;
|
||||
metadata.lastModified = entry.lastModified;
|
||||
metadata.size = entry.size;
|
||||
} else if (entry.type === "directory") {
|
||||
} else if (entry.type === 'directory') {
|
||||
metadata.files = getMatchingEntries(entry, entries).map(e =>
|
||||
getMetadata(e, entries)
|
||||
);
|
||||
|
@ -35,8 +35,8 @@ function serveMetadata(req, res) {
|
|||
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
"Cache-Tag": "meta"
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
'Cache-Tag': 'meta'
|
||||
})
|
||||
.send(metadata);
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
const MainPage = require("../client/MainPage");
|
||||
const renderPage = require("../utils/renderPage");
|
||||
const MainPage = require('../client/MainPage');
|
||||
const renderPage = require('../utils/renderPage');
|
||||
|
||||
const globalScripts =
|
||||
process.env.NODE_ENV === "production"
|
||||
process.env.NODE_ENV === 'production'
|
||||
? [
|
||||
"/react@16.4.1/umd/react.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@16.4.1/umd/react.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@16.4.1/umd/react.development.js",
|
||||
"/react-dom@16.4.1/umd/react-dom.development.js",
|
||||
"/react-router-dom@4.3.1/umd/react-router-dom.js"
|
||||
'/react@16.4.1/umd/react.development.js',
|
||||
'/react-dom@16.4.1/umd/react-dom.development.js',
|
||||
'/react-router-dom@4.3.1/umd/react-router-dom.js'
|
||||
];
|
||||
|
||||
function serveRootPage(req, res) {
|
||||
const scripts = globalScripts.concat(req.assets.getScripts("main"));
|
||||
const styles = req.assets.getStyles("main");
|
||||
const scripts = globalScripts.concat(req.assets.getScripts('main'));
|
||||
const styles = req.assets.getStyles('main');
|
||||
|
||||
const html = renderPage(MainPage, {
|
||||
scripts: scripts,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const path = require("path");
|
||||
const etag = require("etag");
|
||||
const path = require('path');
|
||||
const etag = require('etag');
|
||||
|
||||
const getContentTypeHeader = require("../utils/getContentTypeHeader");
|
||||
const getContentTypeHeader = require('../utils/getContentTypeHeader');
|
||||
|
||||
function serveStaticFile(req, res) {
|
||||
const tags = ["file"];
|
||||
const tags = ['file'];
|
||||
|
||||
const ext = path.extname(req.entry.name).substr(1);
|
||||
if (ext) {
|
||||
|
@ -13,12 +13,12 @@ function serveStaticFile(req, res) {
|
|||
|
||||
res
|
||||
.set({
|
||||
"Content-Length": req.entry.size,
|
||||
"Content-Type": getContentTypeHeader(req.entry.contentType),
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
"Last-Modified": req.entry.lastModified,
|
||||
'Content-Length': req.entry.size,
|
||||
'Content-Type': getContentTypeHeader(req.entry.contentType),
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
'Last-Modified': req.entry.lastModified,
|
||||
ETag: etag(req.entry.content),
|
||||
"Cache-Tag": tags.join(",")
|
||||
'Cache-Tag': tags.join(',')
|
||||
})
|
||||
.send(req.entry.content);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const BlacklistAPI = require("../BlacklistAPI");
|
||||
const BlacklistAPI = require('../BlacklistAPI');
|
||||
|
||||
function showBlacklist(req, res) {
|
||||
BlacklistAPI.getPackages().then(
|
||||
|
@ -8,7 +8,7 @@ function showBlacklist(req, res) {
|
|||
error => {
|
||||
console.error(error);
|
||||
res.status(500).send({
|
||||
error: "Unable to fetch blacklist"
|
||||
error: 'Unable to fetch blacklist'
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const secretKey = require("../secretKey");
|
||||
const secretKey = require('../secretKey');
|
||||
|
||||
function showPublicKey(req, res) {
|
||||
res.send({ publicKey: secretKey.public });
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
const subDays = require("date-fns/sub_days");
|
||||
const startOfDay = require("date-fns/start_of_day");
|
||||
const startOfSecond = require("date-fns/start_of_second");
|
||||
const subDays = require('date-fns/sub_days');
|
||||
const startOfDay = require('date-fns/start_of_day');
|
||||
const startOfSecond = require('date-fns/start_of_second');
|
||||
|
||||
const StatsAPI = require("../StatsAPI");
|
||||
const StatsAPI = require('../StatsAPI');
|
||||
|
||||
function showStats(req, res) {
|
||||
let since, until;
|
||||
switch (req.query.period) {
|
||||
case "last-day":
|
||||
case 'last-day':
|
||||
until = startOfDay(new Date());
|
||||
since = subDays(until, 1);
|
||||
break;
|
||||
case "last-week":
|
||||
case 'last-week':
|
||||
until = startOfDay(new Date());
|
||||
since = subDays(until, 7);
|
||||
break;
|
||||
case "last-month":
|
||||
case 'last-month':
|
||||
until = startOfDay(new Date());
|
||||
since = subDays(until, 30);
|
||||
break;
|
||||
|
@ -27,35 +27,35 @@ function showStats(req, res) {
|
|||
}
|
||||
|
||||
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())) {
|
||||
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) {
|
||||
return res
|
||||
.status(403)
|
||||
.send({ error: "?until date must come after ?since date" });
|
||||
.send({ error: '?until date must come after ?since 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(
|
||||
stats => {
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=60",
|
||||
"Cache-Tag": "stats"
|
||||
'Cache-Control': 'public, max-age=60',
|
||||
'Cache-Tag': 'stats'
|
||||
})
|
||||
.send(stats);
|
||||
},
|
||||
error => {
|
||||
console.error(error);
|
||||
res.status(500).send({ error: "Unable to fetch stats" });
|
||||
res.status(500).send({ error: 'Unable to fetch stats' });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const React = require("react");
|
||||
const PropTypes = require("prop-types");
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
|
||||
const createHTML = require("./utils/createHTML");
|
||||
const x = require("./utils/execScript");
|
||||
const createHTML = require('./utils/createHTML');
|
||||
const x = require('./utils/execScript');
|
||||
|
||||
function MainPage({ title, description, scripts, styles, data, content }) {
|
||||
return (
|
||||
|
@ -17,19 +17,23 @@ function MainPage({ title, description, scripts, styles, data, content }) {
|
|||
/>
|
||||
<meta name="timestamp" content={new Date().toISOString()} />
|
||||
<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(
|
||||
"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(
|
||||
"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)}`)}
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" dangerouslySetInnerHTML={content} />
|
||||
{scripts.map(s => <script key={s} src={s} />)}
|
||||
{scripts.map(s => (
|
||||
<script key={s} src={s} />
|
||||
))}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
@ -49,12 +53,12 @@ MainPage.propTypes = {
|
|||
};
|
||||
|
||||
MainPage.defaultProps = {
|
||||
title: "UNPKG",
|
||||
description: "The CDN for everything on npm",
|
||||
title: 'UNPKG',
|
||||
description: 'The CDN for everything on npm',
|
||||
scripts: [],
|
||||
styles: [],
|
||||
data: {},
|
||||
content: createHTML("")
|
||||
content: createHTML('')
|
||||
};
|
||||
|
||||
module.exports = MainPage;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
require("./autoIndex.css");
|
||||
require('./autoIndex.css');
|
||||
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
|
||||
const App = require("./autoIndex/App");
|
||||
const App = require('./autoIndex/App');
|
||||
|
||||
const props = window.__DATA__ || {};
|
||||
|
||||
ReactDOM.hydrate(<App {...props} />, document.getElementById("root"));
|
||||
ReactDOM.hydrate(<App {...props} />, document.getElementById('root'));
|
||||
|
|
|
@ -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 {
|
||||
static defaultProps = {
|
||||
|
@ -11,8 +11,8 @@ class App extends React.Component {
|
|||
|
||||
handleChange = event => {
|
||||
window.location.href = window.location.href.replace(
|
||||
"@" + this.props.packageVersion,
|
||||
"@" + event.target.value
|
||||
'@' + this.props.packageVersion,
|
||||
'@' + event.target.value
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ class App extends React.Component {
|
|||
</h1>
|
||||
|
||||
<div className="app-version-selector">
|
||||
Version:{" "}
|
||||
Version:{' '}
|
||||
<select
|
||||
id="version"
|
||||
defaultValue={this.props.packageVersion}
|
||||
|
@ -59,8 +59,8 @@ class App extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const PropTypes = require("prop-types");
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const PropTypes = require('prop-types');
|
||||
|
||||
const entryType = PropTypes.object;
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
require("./DirectoryListing.css");
|
||||
require('./DirectoryListing.css');
|
||||
|
||||
const React = require("react");
|
||||
const formatBytes = require("pretty-bytes");
|
||||
const sortBy = require("sort-by");
|
||||
const React = require('react');
|
||||
const formatBytes = require('pretty-bytes');
|
||||
const sortBy = require('sort-by');
|
||||
|
||||
function getDirname(name) {
|
||||
return (
|
||||
name
|
||||
.split("/")
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
.join("/") || "."
|
||||
.join('/') || '.'
|
||||
);
|
||||
}
|
||||
|
||||
function getMatchingEntries(entry, entries) {
|
||||
const dirname = entry.name || ".";
|
||||
const dirname = entry.name || '.';
|
||||
|
||||
return Object.keys(entries)
|
||||
.filter(name => entry.name !== name && getDirname(name) === dirname)
|
||||
|
@ -28,7 +28,7 @@ function getRelativeName(base, name) {
|
|||
function DirectoryListing({ filename, entry, entries }) {
|
||||
const rows = [];
|
||||
|
||||
if (filename !== "/") {
|
||||
if (filename !== '/') {
|
||||
rows.push(
|
||||
<tr key="..">
|
||||
<td>
|
||||
|
@ -46,11 +46,11 @@ function DirectoryListing({ filename, entry, entries }) {
|
|||
const matchingEntries = getMatchingEntries(entry, entries);
|
||||
|
||||
matchingEntries
|
||||
.filter(({ type }) => type === "directory")
|
||||
.sort(sortBy("name"))
|
||||
.filter(({ type }) => type === 'directory')
|
||||
.sort(sortBy('name'))
|
||||
.forEach(({ name }) => {
|
||||
const relName = getRelativeName(entry.name, name);
|
||||
const href = relName + "/";
|
||||
const href = relName + '/';
|
||||
|
||||
rows.push(
|
||||
<tr key={name}>
|
||||
|
@ -67,8 +67,8 @@ function DirectoryListing({ filename, entry, entries }) {
|
|||
});
|
||||
|
||||
matchingEntries
|
||||
.filter(({ type }) => type === "file")
|
||||
.sort(sortBy("name"))
|
||||
.filter(({ type }) => type === 'file')
|
||||
.sort(sortBy('name'))
|
||||
.forEach(({ name, size, contentType, lastModified }) => {
|
||||
const relName = getRelativeName(entry.name, name);
|
||||
|
||||
|
@ -100,7 +100,7 @@ function DirectoryListing({ filename, entry, entries }) {
|
|||
<tbody>
|
||||
{rows.map((row, index) =>
|
||||
React.cloneElement(row, {
|
||||
className: index % 2 ? "odd" : "even"
|
||||
className: index % 2 ? 'odd' : 'even'
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
|
@ -109,8 +109,8 @@ function DirectoryListing({ filename, entry, entries }) {
|
|||
);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
const PropTypes = require("prop-types");
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const PropTypes = require('prop-types');
|
||||
|
||||
const entryType = PropTypes.shape({
|
||||
name: PropTypes.string.isRequired
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
require("./main.css");
|
||||
require('./main.css');
|
||||
|
||||
const React = require("react");
|
||||
const ReactDOM = require("react-dom");
|
||||
const React = require('react');
|
||||
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'));
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
require("./About.css");
|
||||
require('./About.css');
|
||||
|
||||
const React = require("react");
|
||||
const React = require('react');
|
||||
|
||||
const h = require("../utils/createHTML");
|
||||
const markup = require("./About.md");
|
||||
const h = require('../utils/createHTML');
|
||||
const markup = require('./About.md');
|
||||
|
||||
function About() {
|
||||
return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const React = require("react");
|
||||
const { HashRouter } = require("react-router-dom");
|
||||
const React = require('react');
|
||||
const { HashRouter } = require('react-router-dom');
|
||||
|
||||
const Layout = require("./Layout");
|
||||
const Layout = require('./Layout');
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
require("./Home.css");
|
||||
require('./Home.css');
|
||||
|
||||
const React = require("react");
|
||||
const React = require('react');
|
||||
|
||||
const h = require("../utils/createHTML");
|
||||
const markup = require("./Home.md");
|
||||
const h = require('../utils/createHTML');
|
||||
const markup = require('./Home.md');
|
||||
|
||||
function Home() {
|
||||
return <div className="wrapper" dangerouslySetInnerHTML={h(markup)} />;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
require("./Layout.css");
|
||||
require('./Layout.css');
|
||||
|
||||
const React = require("react");
|
||||
const PropTypes = require("prop-types");
|
||||
const { Switch, Route, Link, withRouter } = require("react-router-dom");
|
||||
const { Motion, spring } = require("react-motion");
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const { Switch, Route, Link, withRouter } = require('react-router-dom');
|
||||
const { Motion, spring } = require('react-motion');
|
||||
|
||||
const WindowSize = require("./WindowSize");
|
||||
const About = require("./About");
|
||||
const Stats = require("./Stats");
|
||||
const Home = require("./Home");
|
||||
const WindowSize = require('./WindowSize');
|
||||
const About = require('./About');
|
||||
const Stats = require('./Stats');
|
||||
const Home = require('./Home');
|
||||
|
||||
class Layout extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -26,18 +26,18 @@ class Layout extends React.Component {
|
|||
adjustUnderline = (useSpring = false) => {
|
||||
let itemIndex;
|
||||
switch (this.props.location.pathname) {
|
||||
case "/stats":
|
||||
case '/stats':
|
||||
itemIndex = 1;
|
||||
break;
|
||||
case "/about":
|
||||
case '/about':
|
||||
itemIndex = 2;
|
||||
break;
|
||||
case "/":
|
||||
case '/':
|
||||
default:
|
||||
itemIndex = 0;
|
||||
}
|
||||
|
||||
const itemNodes = this.listNode.querySelectorAll("li");
|
||||
const itemNodes = this.listNode.querySelectorAll('li');
|
||||
const currentNode = itemNodes[itemIndex];
|
||||
|
||||
this.setState({
|
||||
|
@ -50,7 +50,7 @@ class Layout extends React.Component {
|
|||
componentDidMount() {
|
||||
this.adjustUnderline();
|
||||
|
||||
fetch("/api/stats?period=last-month")
|
||||
fetch('/api/stats?period=last-month')
|
||||
.then(res => res.json())
|
||||
.then(stats => this.setState({ stats }));
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
require("./Stats.css");
|
||||
require('./Stats.css');
|
||||
|
||||
const React = require("react");
|
||||
const PropTypes = require("prop-types");
|
||||
const formatBytes = require("pretty-bytes");
|
||||
const formatDate = require("date-fns/format");
|
||||
const parseDate = require("date-fns/parse");
|
||||
const { continents, countries } = require("countries-list");
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const formatBytes = require('pretty-bytes');
|
||||
const formatDate = require('date-fns/format');
|
||||
const parseDate = require('date-fns/parse');
|
||||
const { continents, countries } = require('countries-list');
|
||||
|
||||
const formatNumber = require("../utils/formatNumber");
|
||||
const formatPercent = require("../utils/formatPercent");
|
||||
const formatNumber = require('../utils/formatNumber');
|
||||
const formatPercent = require('../utils/formatPercent');
|
||||
|
||||
function getCountriesByContinent(continent) {
|
||||
return Object.keys(countries).filter(
|
||||
|
@ -68,15 +68,15 @@ class Stats extends React.Component {
|
|||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{formatNumber(requests)} ({formatPercent(
|
||||
requests / totals.requests.all
|
||||
)}%)
|
||||
{formatNumber(requests)} (
|
||||
{formatPercent(requests / totals.requests.all)}
|
||||
%)
|
||||
</td>
|
||||
{bandwidth ? (
|
||||
<td>
|
||||
{formatBytes(bandwidth)} ({formatPercent(
|
||||
bandwidth / totals.bandwidth.all
|
||||
)}%)
|
||||
{formatBytes(bandwidth)} (
|
||||
{formatPercent(bandwidth / totals.bandwidth.all)}
|
||||
%)
|
||||
</td>
|
||||
) : (
|
||||
<td>-</td>
|
||||
|
@ -120,16 +120,16 @@ class Stats extends React.Component {
|
|||
</td>
|
||||
<td>
|
||||
<strong>
|
||||
{formatNumber(continentData.requests)} ({formatPercent(
|
||||
continentData.requests / totals.requests.all
|
||||
)}%)
|
||||
{formatNumber(continentData.requests)} (
|
||||
{formatPercent(continentData.requests / totals.requests.all)}
|
||||
%)
|
||||
</strong>
|
||||
</td>
|
||||
<td>
|
||||
<strong>
|
||||
{formatBytes(continentData.bandwidth)} ({formatPercent(
|
||||
continentData.bandwidth / totals.bandwidth.all
|
||||
)}%)
|
||||
{formatBytes(continentData.bandwidth)} (
|
||||
{formatPercent(continentData.bandwidth / totals.bandwidth.all)}
|
||||
%)
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -148,14 +148,14 @@ class Stats extends React.Component {
|
|||
<tr key={continent + country} className="country-row">
|
||||
<td className="country-name">{countries[country].name}</td>
|
||||
<td>
|
||||
{formatNumber(countryRequests)} ({formatPercent(
|
||||
countryRequests / totals.requests.all
|
||||
)}%)
|
||||
{formatNumber(countryRequests)} (
|
||||
{formatPercent(countryRequests / totals.requests.all)}
|
||||
%)
|
||||
</td>
|
||||
<td>
|
||||
{formatBytes(countryBandwidth)} ({formatPercent(
|
||||
countryBandwidth / totals.bandwidth.all
|
||||
)}%)
|
||||
{formatBytes(countryBandwidth)} (
|
||||
{formatPercent(countryBandwidth / totals.bandwidth.all)}
|
||||
%)
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -176,9 +176,9 @@ class Stats extends React.Component {
|
|||
<tr key={protocol}>
|
||||
<td>{protocol}</td>
|
||||
<td>
|
||||
{formatNumber(requests)} ({formatPercent(
|
||||
requests / sumValues(totals.requests.protocol)
|
||||
)}%)
|
||||
{formatNumber(requests)} (
|
||||
{formatPercent(requests / sumValues(totals.requests.protocol))}
|
||||
%)
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
@ -187,29 +187,29 @@ class Stats extends React.Component {
|
|||
return (
|
||||
<div className="wrapper">
|
||||
<p>
|
||||
From <strong>{formatDate(since, "MMM D")}</strong> to{" "}
|
||||
<strong>{formatDate(until, "MMM D")}</strong> unpkg served{" "}
|
||||
From <strong>{formatDate(since, 'MMM D')}</strong> to{' '}
|
||||
<strong>{formatDate(until, 'MMM D')}</strong> unpkg served{' '}
|
||||
<strong>{formatNumber(totals.requests.all)}</strong> requests and a
|
||||
total of <strong>{formatBytes(totals.bandwidth.all)}</strong> of data
|
||||
to <strong>{formatNumber(totals.uniques.all)}</strong> unique
|
||||
visitors,{" "}
|
||||
visitors,{' '}
|
||||
<strong>
|
||||
{formatPercent(totals.requests.cached / totals.requests.all, 0)}%
|
||||
</strong>{" "}
|
||||
</strong>{' '}
|
||||
of which were served from the cache.
|
||||
</p>
|
||||
|
||||
<h3>Packages</h3>
|
||||
|
||||
<p>
|
||||
The table below shows the most popular packages served by unpkg from{" "}
|
||||
<strong>{formatDate(since, "MMM D")}</strong> to{" "}
|
||||
<strong>{formatDate(until, "MMM D")}</strong>. Only the top{" "}
|
||||
The table below shows the most popular packages served by unpkg from{' '}
|
||||
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
|
||||
<strong>{formatDate(until, 'MMM D')}</strong>. Only the top{' '}
|
||||
{Object.keys(totals.requests.package).length} packages are shown.
|
||||
</p>
|
||||
|
||||
<p className="table-filter">
|
||||
Include only packages that received at least{" "}
|
||||
Include only packages that received at least{' '}
|
||||
<select
|
||||
value={this.state.minPackageRequests}
|
||||
onChange={event =>
|
||||
|
@ -224,11 +224,11 @@ class Stats extends React.Component {
|
|||
<option value="100000">100,000</option>
|
||||
<option value="1000000">1,000,000</option>
|
||||
<option value="10000000">10,000,000</option>
|
||||
</select>{" "}
|
||||
</select>{' '}
|
||||
requests.
|
||||
</p>
|
||||
|
||||
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}>
|
||||
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
|
@ -248,13 +248,13 @@ class Stats extends React.Component {
|
|||
<h3>Regions</h3>
|
||||
|
||||
<p>
|
||||
The table below breaks down requests to unpkg from{" "}
|
||||
<strong>{formatDate(since, "MMM D")}</strong> to{" "}
|
||||
<strong>{formatDate(until, "MMM D")}</strong> by geographic region.
|
||||
The table below breaks down requests to unpkg from{' '}
|
||||
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
|
||||
<strong>{formatDate(until, 'MMM D')}</strong> by geographic region.
|
||||
</p>
|
||||
|
||||
<p className="table-filter">
|
||||
Include only countries that made at least{" "}
|
||||
Include only countries that made at least{' '}
|
||||
<select
|
||||
value={this.state.minCountryRequests}
|
||||
onChange={event =>
|
||||
|
@ -268,14 +268,14 @@ class Stats extends React.Component {
|
|||
<option value="1000000">1,000,000</option>
|
||||
<option value="10000000">10,000,000</option>
|
||||
<option value="100000000">100,000,000</option>
|
||||
</select>{" "}
|
||||
</select>{' '}
|
||||
requests.
|
||||
</p>
|
||||
|
||||
<table
|
||||
cellSpacing="0"
|
||||
cellPadding="0"
|
||||
style={{ width: "100%" }}
|
||||
style={{ width: '100%' }}
|
||||
className="regions-table"
|
||||
>
|
||||
<thead>
|
||||
|
@ -297,12 +297,12 @@ class Stats extends React.Component {
|
|||
<h3>Protocols</h3>
|
||||
|
||||
<p>
|
||||
The table below breaks down requests to unpkg from{" "}
|
||||
<strong>{formatDate(since, "MMM D")}</strong> to{" "}
|
||||
<strong>{formatDate(until, "MMM D")}</strong> by HTTP protocol.
|
||||
The table below breaks down requests to unpkg from{' '}
|
||||
<strong>{formatDate(since, 'MMM D')}</strong> to{' '}
|
||||
<strong>{formatDate(until, 'MMM D')}</strong> by HTTP protocol.
|
||||
</p>
|
||||
|
||||
<table cellSpacing="0" cellPadding="0" style={{ width: "100%" }}>
|
||||
<table cellSpacing="0" cellPadding="0" style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const React = require("react");
|
||||
const PropTypes = require("prop-types");
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
|
||||
const addEvent = require("../utils/addEvent");
|
||||
const removeEvent = require("../utils/removeEvent");
|
||||
const addEvent = require('../utils/addEvent');
|
||||
const removeEvent = require('../utils/removeEvent');
|
||||
|
||||
const resizeEvent = "resize";
|
||||
const resizeEvent = 'resize';
|
||||
|
||||
class WindowSize extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -2,7 +2,7 @@ function addEvent(node, type, handler) {
|
|||
if (node.addEventListener) {
|
||||
node.addEventListener(type, handler, false);
|
||||
} else if (node.attachEvent) {
|
||||
node.attachEvent("on" + type, handler);
|
||||
node.attachEvent('on' + type, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const React = require("react");
|
||||
const React = require('react');
|
||||
|
||||
const h = require("./createHTML");
|
||||
const h = require('./createHTML');
|
||||
|
||||
function execScript(code) {
|
||||
return <script dangerouslySetInnerHTML={h(code)} />;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
function formatNumber(n) {
|
||||
const digits = String(n).split("");
|
||||
const digits = String(n).split('');
|
||||
const groups = [];
|
||||
|
||||
while (digits.length) {
|
||||
groups.unshift(digits.splice(-3).join(""));
|
||||
groups.unshift(digits.splice(-3).join(''));
|
||||
}
|
||||
|
||||
return groups.join(",");
|
||||
return groups.join(',');
|
||||
}
|
||||
|
||||
module.exports = formatNumber;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
function parseNumber(s) {
|
||||
return parseInt(s.replace(/,/g, ""), 10) || 0;
|
||||
return parseInt(s.replace(/,/g, ''), 10) || 0;
|
||||
}
|
||||
|
||||
module.exports = parseNumber;
|
||||
|
|
|
@ -2,7 +2,7 @@ function removeEvent(node, type, handler) {
|
|||
if (node.removeEventListener) {
|
||||
node.removeEventListener(type, handler, false);
|
||||
} else if (node.detachEvent) {
|
||||
node.detachEvent("on" + type, handler);
|
||||
node.detachEvent('on' + type, handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Use babel to compile JSX on the fly.
|
||||
require("@babel/register")({
|
||||
require('@babel/register')({
|
||||
only: [/modules\/client/]
|
||||
});
|
||||
|
||||
// Ignore require("*.css") calls.
|
||||
require.extensions[".css"] = function() {
|
||||
require.extensions['.css'] = function() {
|
||||
return {};
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const webpack = require("webpack");
|
||||
const webpack = require('webpack');
|
||||
|
||||
/**
|
||||
* Returns a modified copy of the given webpackEntry object with
|
||||
* the moduleId in front of all other assets.
|
||||
*/
|
||||
function prependModuleId(webpackEntry, moduleId) {
|
||||
if (typeof webpackEntry === "string") {
|
||||
if (typeof webpackEntry === 'string') {
|
||||
return [moduleId, webpackEntry];
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ function prependModuleId(webpackEntry, moduleId) {
|
|||
return [moduleId, ...webpackEntry];
|
||||
}
|
||||
|
||||
if (webpackEntry && typeof webpackEntry === "object") {
|
||||
if (webpackEntry && typeof webpackEntry === 'object') {
|
||||
const entry = { ...webpackEntry };
|
||||
|
||||
for (const chunkName in entry) {
|
||||
|
@ -25,7 +25,7 @@ function prependModuleId(webpackEntry, moduleId) {
|
|||
return entry;
|
||||
}
|
||||
|
||||
throw new Error("Invalid webpack entry object");
|
||||
throw new Error('Invalid webpack entry object');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
const express = require("express");
|
||||
const morgan = require("morgan");
|
||||
const WebpackDevServer = require("webpack-dev-server");
|
||||
const devErrorHandler = require("errorhandler");
|
||||
const express = require('express');
|
||||
const morgan = require('morgan');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const devErrorHandler = require('errorhandler');
|
||||
|
||||
const devAssets = require("./middleware/devAssets");
|
||||
const createDevCompiler = require("./createDevCompiler");
|
||||
const createRouter = require("./createRouter");
|
||||
const devAssets = require('./middleware/devAssets');
|
||||
const createDevCompiler = require('./createDevCompiler');
|
||||
const createRouter = require('./createRouter');
|
||||
|
||||
function createDevServer(publicDir, webpackConfig, devOrigin) {
|
||||
const compiler = createDevCompiler(
|
||||
|
@ -33,8 +33,8 @@ function createDevServer(publicDir, webpackConfig, devOrigin) {
|
|||
disableHostCheck: true,
|
||||
before(app) {
|
||||
// This runs before webpack-dev-middleware
|
||||
app.disable("x-powered-by");
|
||||
app.use(morgan("dev"));
|
||||
app.disable('x-powered-by');
|
||||
app.use(morgan('dev'));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const express = require("express");
|
||||
const bodyParser = require("body-parser");
|
||||
const cors = require("cors");
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const cors = require('cors');
|
||||
|
||||
function route(setup) {
|
||||
const app = express.Router();
|
||||
|
@ -11,92 +11,92 @@ function route(setup) {
|
|||
function createRouter() {
|
||||
const app = express.Router();
|
||||
|
||||
app.get("/", require("./actions/serveRootPage"));
|
||||
app.get('/', require('./actions/serveRootPage'));
|
||||
|
||||
app.use(cors());
|
||||
app.use(bodyParser.json());
|
||||
app.use(require("./middleware/userToken"));
|
||||
app.use(require('./middleware/userToken'));
|
||||
|
||||
app.use(
|
||||
"/api",
|
||||
'/api',
|
||||
route(app => {
|
||||
app.get("/publicKey", require("./actions/showPublicKey"));
|
||||
app.get('/publicKey', require('./actions/showPublicKey'));
|
||||
|
||||
app.post("/auth", require("./actions/createAuth"));
|
||||
app.get("/auth", require("./actions/showAuth"));
|
||||
app.post('/auth', require('./actions/createAuth'));
|
||||
app.get('/auth', require('./actions/showAuth'));
|
||||
|
||||
app.post(
|
||||
"/blacklist",
|
||||
require("./middleware/requireAuth")("blacklist.add"),
|
||||
require("./actions/addToBlacklist")
|
||||
'/blacklist',
|
||||
require('./middleware/requireAuth')('blacklist.add'),
|
||||
require('./actions/addToBlacklist')
|
||||
);
|
||||
app.get(
|
||||
"/blacklist",
|
||||
require("./middleware/requireAuth")("blacklist.read"),
|
||||
require("./actions/showBlacklist")
|
||||
'/blacklist',
|
||||
require('./middleware/requireAuth')('blacklist.read'),
|
||||
require('./actions/showBlacklist')
|
||||
);
|
||||
app.delete(
|
||||
"/blacklist",
|
||||
require("./middleware/requireAuth")("blacklist.remove"),
|
||||
require("./actions/removeFromBlacklist")
|
||||
'/blacklist',
|
||||
require('./middleware/requireAuth')('blacklist.remove'),
|
||||
require('./actions/removeFromBlacklist')
|
||||
);
|
||||
|
||||
if (process.env.NODE_ENV !== "test") {
|
||||
app.get("/stats", require("./actions/showStats"));
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.get('/stats', require('./actions/showStats'));
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: Remove
|
||||
app.get("/_publicKey", require("./actions/showPublicKey"));
|
||||
app.get('/_publicKey', require('./actions/showPublicKey'));
|
||||
|
||||
// TODO: Remove
|
||||
app.use(
|
||||
"/_auth",
|
||||
'/_auth',
|
||||
route(app => {
|
||||
app.post("/", require("./actions/createAuth"));
|
||||
app.get("/", require("./actions/showAuth"));
|
||||
app.post('/', require('./actions/createAuth'));
|
||||
app.get('/', require('./actions/showAuth'));
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: Remove
|
||||
app.use(
|
||||
"/_blacklist",
|
||||
'/_blacklist',
|
||||
route(app => {
|
||||
app.post(
|
||||
"/",
|
||||
require("./middleware/requireAuth")("blacklist.add"),
|
||||
require("./actions/addToBlacklist")
|
||||
'/',
|
||||
require('./middleware/requireAuth')('blacklist.add'),
|
||||
require('./actions/addToBlacklist')
|
||||
);
|
||||
app.get(
|
||||
"/",
|
||||
require("./middleware/requireAuth")("blacklist.read"),
|
||||
require("./actions/showBlacklist")
|
||||
'/',
|
||||
require('./middleware/requireAuth')('blacklist.read'),
|
||||
require('./actions/showBlacklist')
|
||||
);
|
||||
app.delete(
|
||||
"*",
|
||||
require("./middleware/requireAuth")("blacklist.remove"),
|
||||
require("./middleware/validatePackageURL"),
|
||||
require("./actions/removeFromBlacklist")
|
||||
'*',
|
||||
require('./middleware/requireAuth')('blacklist.remove'),
|
||||
require('./middleware/validatePackageURL'),
|
||||
require('./actions/removeFromBlacklist')
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: Remove
|
||||
if (process.env.NODE_ENV !== "test") {
|
||||
app.get("/_stats", require("./actions/showStats"));
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.get('/_stats', require('./actions/showStats'));
|
||||
}
|
||||
|
||||
app.get(
|
||||
"*",
|
||||
require("./middleware/redirectLegacyURLs"),
|
||||
require("./middleware/validatePackageURL"),
|
||||
require("./middleware/validatePackageName"),
|
||||
require("./middleware/validateQuery"),
|
||||
require("./middleware/checkBlacklist"),
|
||||
require("./middleware/fetchPackage"),
|
||||
require("./middleware/findFile"),
|
||||
require("./actions/serveFile")
|
||||
'*',
|
||||
require('./middleware/redirectLegacyURLs'),
|
||||
require('./middleware/validatePackageURL'),
|
||||
require('./middleware/validatePackageName'),
|
||||
require('./middleware/validateQuery'),
|
||||
require('./middleware/checkBlacklist'),
|
||||
require('./middleware/fetchPackage'),
|
||||
require('./middleware/findFile'),
|
||||
require('./actions/serveFile')
|
||||
);
|
||||
|
||||
return app;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
const http = require("http");
|
||||
const express = require("express");
|
||||
const morgan = require("morgan");
|
||||
const raven = require("raven");
|
||||
const http = require('http');
|
||||
const express = require('express');
|
||||
const morgan = require('morgan');
|
||||
const raven = require('raven');
|
||||
|
||||
const staticAssets = require("./middleware/staticAssets");
|
||||
const createRouter = require("./createRouter");
|
||||
const staticAssets = require('./middleware/staticAssets');
|
||||
const createRouter = require('./createRouter');
|
||||
|
||||
morgan.token("fwd", req => {
|
||||
const fwd = req.get("x-forwarded-for");
|
||||
return fwd ? fwd.replace(/\s/g, "") : "-";
|
||||
morgan.token('fwd', req => {
|
||||
const fwd = req.get('x-forwarded-for');
|
||||
return fwd ? fwd.replace(/\s/g, '') : '-';
|
||||
});
|
||||
|
||||
if (process.env.SENTRY_DSN) {
|
||||
|
@ -34,13 +34,13 @@ if (process.env.SENTRY_DSN) {
|
|||
function createServer(publicDir, statsFile) {
|
||||
const app = express();
|
||||
|
||||
app.disable("x-powered-by");
|
||||
app.disable('x-powered-by');
|
||||
|
||||
if (process.env.SENTRY_DSN) {
|
||||
app.use(raven.requestHandler());
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== "test") {
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.use(
|
||||
morgan(
|
||||
// Modified version of Heroku's log format
|
||||
|
@ -53,7 +53,7 @@ function createServer(publicDir, statsFile) {
|
|||
// app.use(errorHandler);
|
||||
|
||||
if (publicDir) {
|
||||
app.use(express.static(publicDir, { maxAge: "365d" }));
|
||||
app.use(express.static(publicDir, { maxAge: '365d' }));
|
||||
}
|
||||
|
||||
if (statsFile) {
|
||||
|
@ -76,14 +76,14 @@ function createServer(publicDir, statsFile) {
|
|||
|
||||
socket.end(
|
||||
[
|
||||
"HTTP/1.1 503 Service Unavailable",
|
||||
"Date: " + new Date().toGMTString(),
|
||||
"Content-Length: " + Buffer.byteLength(message),
|
||||
"Content-Type: text/plain",
|
||||
"Connection: close",
|
||||
"",
|
||||
'HTTP/1.1 503 Service Unavailable',
|
||||
'Date: ' + new Date().toGMTString(),
|
||||
'Content-Length: ' + Buffer.byteLength(message),
|
||||
'Content-Type: text/plain',
|
||||
'Connection: close',
|
||||
'',
|
||||
message
|
||||
].join("\r\n")
|
||||
].join('\r\n')
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
const parseURL = require("url").parse;
|
||||
const startOfDay = require("date-fns/start_of_day");
|
||||
const addDays = require("date-fns/add_days");
|
||||
const parseURL = require('url').parse;
|
||||
const startOfDay = require('date-fns/start_of_day');
|
||||
const addDays = require('date-fns/add_days');
|
||||
|
||||
const db = require("./utils/data");
|
||||
const isValidPackageName = require("./utils/isValidPackageName");
|
||||
const parsePackageURL = require("./utils/parsePackageURL");
|
||||
const logging = require("./utils/logging");
|
||||
const db = require('./utils/data');
|
||||
const isValidPackageName = require('./utils/isValidPackageName');
|
||||
const parsePackageURL = require('./utils/parsePackageURL');
|
||||
const logging = require('./utils/logging');
|
||||
|
||||
const CloudflareAPI = require("./CloudflareAPI");
|
||||
const StatsAPI = require("./StatsAPI");
|
||||
const CloudflareAPI = require('./CloudflareAPI');
|
||||
const StatsAPI = require('./StatsAPI');
|
||||
|
||||
/**
|
||||
* Domains we want to analyze.
|
||||
*/
|
||||
const domainNames = [
|
||||
"unpkg.com"
|
||||
'unpkg.com'
|
||||
//"npmcdn.com" // We don't have log data on npmcdn.com yet :/
|
||||
];
|
||||
|
||||
|
@ -25,7 +25,7 @@ function getSeconds(date) {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -45,8 +45,8 @@ function computeCounters(stream) {
|
|||
}
|
||||
|
||||
stream
|
||||
.on("error", reject)
|
||||
.on("data", entry => {
|
||||
.on('error', reject)
|
||||
.on('data', entry => {
|
||||
totalEntries += 1;
|
||||
|
||||
const date = new Date(Math.round(entry.EdgeStartTimestamp / 1000000));
|
||||
|
@ -105,7 +105,7 @@ function computeCounters(stream) {
|
|||
);
|
||||
}
|
||||
})
|
||||
.on("end", () => {
|
||||
.on('end', () => {
|
||||
resolve({ counters, expireat, totalEntries });
|
||||
});
|
||||
});
|
||||
|
@ -137,12 +137,12 @@ function ingestLogsForZone(zone, startDate, endDate) {
|
|||
|
||||
const startFetchTime = Date.now();
|
||||
const fields = [
|
||||
"EdgeStartTimestamp",
|
||||
"EdgeResponseStatus",
|
||||
"EdgeResponseBytes",
|
||||
"ClientRequestProtocol",
|
||||
"ClientRequestURI",
|
||||
"ClientRequestReferer"
|
||||
'EdgeStartTimestamp',
|
||||
'EdgeResponseStatus',
|
||||
'EdgeResponseBytes',
|
||||
'ClientRequestProtocol',
|
||||
'ClientRequestURI',
|
||||
'ClientRequestReferer'
|
||||
];
|
||||
|
||||
return CloudflareAPI.getLogs(
|
||||
|
@ -154,7 +154,7 @@ function ingestLogsForZone(zone, startDate, endDate) {
|
|||
const endFetchTime = Date.now();
|
||||
|
||||
logging.info(
|
||||
"Fetched logs for %s from %s to %s (%dms)",
|
||||
'Fetched logs for %s from %s to %s (%dms)',
|
||||
zone.name,
|
||||
stringifySeconds(startSeconds),
|
||||
stringifySeconds(endSeconds),
|
||||
|
@ -167,7 +167,7 @@ function ingestLogsForZone(zone, startDate, endDate) {
|
|||
const endProcessTime = Date.now();
|
||||
|
||||
logging.info(
|
||||
"Processed %d log entries for %s (%dms)",
|
||||
'Processed %d log entries for %s (%dms)',
|
||||
totalEntries,
|
||||
zone.name,
|
||||
endProcessTime - startProcessTime
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const addMinutes = require("date-fns/add_minutes");
|
||||
const startOfMinute = require("date-fns/start_of_minute");
|
||||
const addMinutes = require('date-fns/add_minutes');
|
||||
const startOfMinute = require('date-fns/start_of_minute');
|
||||
|
||||
const ingestLogs = require("./ingestLogs");
|
||||
const ingestLogs = require('./ingestLogs');
|
||||
|
||||
const oneSecond = 1000;
|
||||
const oneMinute = oneSecond * 60;
|
||||
|
@ -26,18 +26,18 @@ function work() {
|
|||
}
|
||||
|
||||
function shutdown() {
|
||||
console.log("Shutting down...");
|
||||
console.log('Shutting down...');
|
||||
|
||||
clearInterval(timer);
|
||||
|
||||
currentWorkload.then(() => {
|
||||
console.log("Goodbye!");
|
||||
console.log('Goodbye!');
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
work();
|
||||
|
||||
process.on("SIGINT", shutdown).on("SIGTERM", shutdown);
|
||||
process.on('SIGINT', shutdown).on('SIGTERM', shutdown);
|
||||
|
||||
timer = setInterval(work, oneMinute);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const BlacklistAPI = require("../BlacklistAPI");
|
||||
const BlacklistAPI = require('../BlacklistAPI');
|
||||
|
||||
function checkBlacklist(req, res, next) {
|
||||
BlacklistAPI.includesPackage(req.packageName).then(
|
||||
|
@ -7,14 +7,14 @@ function checkBlacklist(req, res, next) {
|
|||
if (blacklisted) {
|
||||
res
|
||||
.status(403)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Package "${req.packageName}" is blacklisted`);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.error("Unable to fetch the blacklist: %s", error);
|
||||
console.error('Unable to fetch the blacklist: %s', error);
|
||||
|
||||
// Continue anyway.
|
||||
next();
|
||||
|
|
|
@ -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
|
||||
|
@ -9,15 +9,15 @@ const createAssets = require("./utils/createAssets");
|
|||
*/
|
||||
function devAssets(webpackCompiler) {
|
||||
let assets;
|
||||
webpackCompiler.plugin("done", stats => {
|
||||
webpackCompiler.plugin('done', stats => {
|
||||
assets = createAssets(stats.toJson());
|
||||
});
|
||||
|
||||
return (req, res, next) => {
|
||||
invariant(
|
||||
assets != null,
|
||||
"devAssets middleware needs a running compiler; " +
|
||||
"use webpack-dev-middleware in front of devAssets"
|
||||
'devAssets middleware needs a running compiler; ' +
|
||||
'use webpack-dev-middleware in front of devAssets'
|
||||
);
|
||||
|
||||
req.assets = assets;
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
const semver = require("semver");
|
||||
const semver = require('semver');
|
||||
|
||||
const addLeadingSlash = require("../utils/addLeadingSlash");
|
||||
const createPackageURL = require("../utils/createPackageURL");
|
||||
const createSearch = require("../utils/createSearch");
|
||||
const getNpmPackageInfo = require("../utils/getNpmPackageInfo");
|
||||
const incrementCounter = require("../utils/incrementCounter");
|
||||
const addLeadingSlash = require('../utils/addLeadingSlash');
|
||||
const createPackageURL = require('../utils/createPackageURL');
|
||||
const createSearch = require('../utils/createSearch');
|
||||
const getNpmPackageInfo = require('../utils/getNpmPackageInfo');
|
||||
const incrementCounter = require('../utils/incrementCounter');
|
||||
|
||||
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.
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=60",
|
||||
"Cache-Tag": "redirect,tag-redirect"
|
||||
'Cache-Control': 'public, max-age=60',
|
||||
'Cache-Tag': 'redirect,tag-redirect'
|
||||
})
|
||||
.redirect(
|
||||
302,
|
||||
|
@ -31,8 +31,8 @@ function semverRedirect(req, res) {
|
|||
// Cache semver redirects for 1 minute.
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=60",
|
||||
"Cache-Tag": "redirect,semver-redirect"
|
||||
'Cache-Control': 'public, max-age=60',
|
||||
'Cache-Tag': 'redirect,semver-redirect'
|
||||
})
|
||||
.redirect(
|
||||
302,
|
||||
|
@ -41,7 +41,7 @@ function semverRedirect(req, res) {
|
|||
} else {
|
||||
res
|
||||
.status(404)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Cannot find package ${req.packageSpec}`);
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +52,12 @@ function filenameRedirect(req, res) {
|
|||
// See https://github.com/rollup/rollup/wiki/pkg.module
|
||||
filename =
|
||||
req.packageConfig.module ||
|
||||
req.packageConfig["jsnext:main"] ||
|
||||
"/index.js";
|
||||
req.packageConfig['jsnext:main'] ||
|
||||
'/index.js';
|
||||
} else if (
|
||||
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
|
||||
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
|
||||
// remove this functionality.
|
||||
incrementCounter(
|
||||
"package-json-custom-main",
|
||||
req.packageSpec + "?main=" + req.query.main,
|
||||
'package-json-custom-main',
|
||||
req.packageSpec + '?main=' + req.query.main,
|
||||
1
|
||||
);
|
||||
} else if (
|
||||
req.packageConfig.unpkg &&
|
||||
typeof req.packageConfig.unpkg === "string"
|
||||
typeof req.packageConfig.unpkg === 'string'
|
||||
) {
|
||||
filename = req.packageConfig.unpkg;
|
||||
} else if (
|
||||
req.packageConfig.browser &&
|
||||
typeof req.packageConfig.browser === "string"
|
||||
typeof req.packageConfig.browser === 'string'
|
||||
) {
|
||||
// Deprecated, see #63
|
||||
filename = req.packageConfig.browser;
|
||||
|
||||
// Count which packages are using this so we can warn them when we
|
||||
// remove this functionality.
|
||||
incrementCounter("package-json-browser-fallback", req.packageSpec, 1);
|
||||
incrementCounter('package-json-browser-fallback', req.packageSpec, 1);
|
||||
} else {
|
||||
filename = req.packageConfig.main || "/index.js";
|
||||
filename = req.packageConfig.main || '/index.js';
|
||||
}
|
||||
|
||||
// Redirect to the exact filename so relative imports
|
||||
// and URLs resolve correctly.
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
"Cache-Tag": "redirect, filename-redirect"
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
'Cache-Tag': 'redirect, filename-redirect'
|
||||
})
|
||||
.redirect(
|
||||
302,
|
||||
|
@ -117,7 +117,7 @@ function fetchPackage(req, res, next) {
|
|||
if (packageInfo == null || packageInfo.versions == null) {
|
||||
return res
|
||||
.status(404)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Cannot find package "${req.packageName}"`);
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ function fetchPackage(req, res, next) {
|
|||
|
||||
if (!req.packageConfig) {
|
||||
// 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);
|
||||
} else {
|
||||
return semverRedirect(req, res);
|
||||
|
@ -144,7 +144,7 @@ function fetchPackage(req, res, next) {
|
|||
|
||||
return res
|
||||
.status(500)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Cannot get info for package "${req.packageName}"`);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
const path = require("path");
|
||||
const path = require('path');
|
||||
|
||||
const addLeadingSlash = require("../utils/addLeadingSlash");
|
||||
const createPackageURL = require("../utils/createPackageURL");
|
||||
const createSearch = require("../utils/createSearch");
|
||||
const fetchNpmPackage = require("../utils/fetchNpmPackage");
|
||||
const getIntegrity = require("../utils/getIntegrity");
|
||||
const getContentType = require("../utils/getContentType");
|
||||
const addLeadingSlash = require('../utils/addLeadingSlash');
|
||||
const createPackageURL = require('../utils/createPackageURL');
|
||||
const createSearch = require('../utils/createSearch');
|
||||
const fetchNpmPackage = require('../utils/fetchNpmPackage');
|
||||
const getIntegrity = require('../utils/getIntegrity');
|
||||
const getContentType = require('../utils/getContentType');
|
||||
|
||||
function indexRedirect(req, res, entry) {
|
||||
// Redirect to the index file so relative imports
|
||||
// resolve correctly.
|
||||
res
|
||||
.set({
|
||||
"Cache-Control": "public, max-age=31536000, immutable", // 1 year
|
||||
"Cache-Tag": "redirect, index-redirect"
|
||||
'Cache-Control': 'public, max-age=31536000, immutable', // 1 year
|
||||
'Cache-Tag': 'redirect, index-redirect'
|
||||
})
|
||||
.redirect(
|
||||
302,
|
||||
|
@ -27,7 +27,7 @@ function indexRedirect(req, res, entry) {
|
|||
}
|
||||
|
||||
function stripLeadingSegment(name) {
|
||||
return name.replace(/^[^/]+\/?/, "");
|
||||
return name.replace(/^[^/]+\/?/, '');
|
||||
}
|
||||
|
||||
function searchEntries(tarballStream, entryName, wantsIndex) {
|
||||
|
@ -35,14 +35,14 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
|
|||
const entries = {};
|
||||
let foundEntry = null;
|
||||
|
||||
if (entryName === "") {
|
||||
foundEntry = entries[""] = { name: "", type: "directory" };
|
||||
if (entryName === '') {
|
||||
foundEntry = entries[''] = { name: '', type: 'directory' };
|
||||
}
|
||||
|
||||
tarballStream
|
||||
.on("error", reject)
|
||||
.on("finish", () => resolve({ entries, foundEntry }))
|
||||
.on("entry", (header, stream, next) => {
|
||||
.on('error', reject)
|
||||
.on('finish', () => resolve({ entries, foundEntry }))
|
||||
.on('entry', (header, stream, next) => {
|
||||
const entry = {
|
||||
// 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
|
||||
|
@ -53,9 +53,9 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
|
|||
};
|
||||
|
||||
// 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.on("end", next);
|
||||
stream.on('end', next);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -65,8 +65,8 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
|
|||
// that are in this file's path. Some tarballs omit these entries
|
||||
// for some reason, so this is the brute force method.
|
||||
let dirname = path.dirname(entry.name);
|
||||
while (dirname !== ".") {
|
||||
const directoryEntry = { name: dirname, type: "directory" };
|
||||
while (dirname !== '.') {
|
||||
const directoryEntry = { name: dirname, type: 'directory' };
|
||||
|
||||
if (!entries[dirname]) {
|
||||
entries[dirname] = directoryEntry;
|
||||
|
@ -94,7 +94,7 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
|
|||
|
||||
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);
|
||||
|
||||
// Set some extra properties for files that we will
|
||||
|
@ -126,8 +126,8 @@ const trailingSlash = /\/$/;
|
|||
function findFile(req, res, next) {
|
||||
fetchNpmPackage(req.packageConfig).then(tarballStream => {
|
||||
const entryName = req.filename
|
||||
.replace(trailingSlash, "")
|
||||
.replace(leadingSlash, "");
|
||||
.replace(trailingSlash, '')
|
||||
.replace(leadingSlash, '');
|
||||
const wantsIndex = trailingSlash.test(req.filename);
|
||||
|
||||
searchEntries(tarballStream, entryName, wantsIndex).then(
|
||||
|
@ -135,7 +135,7 @@ function findFile(req, res, next) {
|
|||
if (!foundEntry) {
|
||||
return res
|
||||
.status(404)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.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
|
||||
// to require("lib") in node where it searches for `lib/index.js`
|
||||
// and `lib/index.json` when `lib` is a directory.
|
||||
if (foundEntry.type === "directory" && !wantsIndex) {
|
||||
if (foundEntry.type === 'directory' && !wantsIndex) {
|
||||
const indexEntry =
|
||||
entries[path.join(entryName, "index.js")] ||
|
||||
entries[path.join(entryName, "index.json")];
|
||||
entries[path.join(entryName, 'index.js')] ||
|
||||
entries[path.join(entryName, 'index.json')];
|
||||
|
||||
if (indexEntry && indexEntry.type === "file") {
|
||||
if (indexEntry && indexEntry.type === 'file') {
|
||||
return indexRedirect(req, res, indexEntry);
|
||||
} else {
|
||||
return res
|
||||
.status(404)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(
|
||||
`Cannot find an index in "${req.filename}" in ${
|
||||
req.packageSpec
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const createSearch = require("../utils/createSearch");
|
||||
const createSearch = require('../utils/createSearch');
|
||||
|
||||
/**
|
||||
* Redirect old URLs that we no longer support.
|
||||
|
@ -6,14 +6,14 @@ const createSearch = require("../utils/createSearch");
|
|||
function redirectLegacyURLs(req, res, next) {
|
||||
// Permanently redirect /_meta/path to /path?meta.
|
||||
if (req.path.match(/^\/_meta\//)) {
|
||||
req.query.meta = "";
|
||||
req.query.meta = '';
|
||||
return res.redirect(301, req.path.substr(6) + createSearch(req.query));
|
||||
}
|
||||
|
||||
// Permanently redirect /path?json => /path?meta
|
||||
if (req.query.json != null) {
|
||||
delete req.query.json;
|
||||
req.query.meta = "";
|
||||
req.query.meta = '';
|
||||
return res.redirect(301, req.path + createSearch(req.query));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
*/
|
||||
function requireAuth(scope) {
|
||||
let checkScopes;
|
||||
if (scope.includes(".")) {
|
||||
const parts = scope.split(".");
|
||||
if (scope.includes('.')) {
|
||||
const parts = scope.split('.');
|
||||
checkScopes = scopes =>
|
||||
parts.reduce((memo, part) => memo && memo[part], scopes) != null;
|
||||
} else {
|
||||
|
@ -20,11 +20,11 @@ function requireAuth(scope) {
|
|||
const user = req.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)) {
|
||||
return res.status(403).send({ error: "Insufficient scopes" });
|
||||
return res.status(403).send({ error: 'Insufficient scopes' });
|
||||
}
|
||||
|
||||
if (req.auth) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const fs = require("fs");
|
||||
const invariant = require("invariant");
|
||||
const fs = require('fs');
|
||||
const invariant = require('invariant');
|
||||
|
||||
const createAssets = require("./utils/createAssets");
|
||||
const createAssets = require('./utils/createAssets');
|
||||
|
||||
/**
|
||||
* An express middleware that sets req.assets from the build
|
||||
|
@ -10,12 +10,12 @@ const createAssets = require("./utils/createAssets");
|
|||
function staticAssets(webpackStatsFile) {
|
||||
let stats;
|
||||
try {
|
||||
stats = JSON.parse(fs.readFileSync(webpackStatsFile, "utf8"));
|
||||
stats = JSON.parse(fs.readFileSync(webpackStatsFile, 'utf8'));
|
||||
} catch (error) {
|
||||
invariant(
|
||||
false,
|
||||
"staticAssets middleware cannot read the build stats in %s; " +
|
||||
"run the `build` script before starting the server",
|
||||
'staticAssets middleware cannot read the build stats in %s; ' +
|
||||
'run the `build` script before starting the server',
|
||||
webpackStatsFile
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const AuthAPI = require("../AuthAPI");
|
||||
const AuthAPI = require('../AuthAPI');
|
||||
|
||||
const ReadMethods = { GET: true, HEAD: true };
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
const auth = req.get("Authorization");
|
||||
const auth = req.get('Authorization');
|
||||
const token = auth
|
||||
? decodeBase64(auth)
|
||||
: (ReadMethods[req.method] ? req.query : req.body).token;
|
||||
|
@ -30,7 +30,7 @@ function userToken(req, res, next) {
|
|||
next();
|
||||
},
|
||||
error => {
|
||||
if (error.name === "JsonWebTokenError") {
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
res.status(403).send({
|
||||
error: `Bad auth token: ${error.message}`
|
||||
});
|
||||
|
@ -38,7 +38,7 @@ function userToken(req, res, next) {
|
|||
console.error(error);
|
||||
|
||||
res.status(500).send({
|
||||
error: "Unable to verify auth"
|
||||
error: 'Unable to verify auth'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ function createAssets(webpackStats) {
|
|||
/**
|
||||
* 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])
|
||||
.reduce((memo, chunk) => memo.concat(assetsByChunkName[chunk] || []), [])
|
||||
.map(createURL);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const validateNpmPackageName = require("validate-npm-package-name");
|
||||
const validateNpmPackageName = require('validate-npm-package-name');
|
||||
|
||||
const hexValue = /^[a-f0-9]+$/i;
|
||||
|
||||
|
@ -13,18 +13,18 @@ function validatePackageName(req, res, next) {
|
|||
if (isHash(req.packageName)) {
|
||||
return res
|
||||
.status(403)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Invalid package name "${req.packageName}" (cannot be a hash)`);
|
||||
}
|
||||
|
||||
const errors = validateNpmPackageName(req.packageName).errors;
|
||||
|
||||
if (errors) {
|
||||
const reason = errors.join(", ");
|
||||
const reason = errors.join(', ');
|
||||
|
||||
return res
|
||||
.status(403)
|
||||
.type("text")
|
||||
.type('text')
|
||||
.send(`Invalid package name "${req.packageName}" (${reason})`);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const createSearch = require("../utils/createSearch");
|
||||
const createSearch = require('../utils/createSearch');
|
||||
|
||||
const knownQueryParams = {
|
||||
main: true, // Deprecated, see #63
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const babel = require("babel-core");
|
||||
const unpkgRewrite = require("../unpkgRewrite");
|
||||
const babel = require('babel-core');
|
||||
const unpkgRewrite = require('../unpkgRewrite');
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
|
@ -66,13 +66,13 @@ const testCases = [
|
|||
];
|
||||
|
||||
const dependencies = {
|
||||
react: "15.6.1",
|
||||
"@angular/router": "4.3.5",
|
||||
"lodash.map": "4.6.0",
|
||||
pn: "1.0.0"
|
||||
react: '15.6.1',
|
||||
'@angular/router': '4.3.5',
|
||||
'lodash.map': '4.6.0',
|
||||
pn: '1.0.0'
|
||||
};
|
||||
|
||||
describe("Rewriting imports/exports", () => {
|
||||
describe('Rewriting imports/exports', () => {
|
||||
testCases.forEach(testCase => {
|
||||
it(`successfully rewrites '${testCase.before}'`, () => {
|
||||
const result = babel.transform(testCase.before, {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const URL = require("whatwg-url");
|
||||
const warning = require("warning");
|
||||
const URL = require('whatwg-url');
|
||||
const warning = require('warning');
|
||||
|
||||
const origin = require("../serverConfig").origin;
|
||||
const origin = require('../serverConfig').origin;
|
||||
|
||||
const bareIdentifierFormat = /^((?:@[^/]+\/)?[^/]+)(\/.*)?$/;
|
||||
|
||||
|
@ -10,7 +10,7 @@ function isValidURL(value) {
|
|||
}
|
||||
|
||||
function isProbablyURLWithoutProtocol(value) {
|
||||
return value.substr(0, 2) === "//";
|
||||
return value.substr(0, 2) === '//';
|
||||
}
|
||||
|
||||
function isAbsoluteURL(value) {
|
||||
|
@ -18,7 +18,7 @@ function isAbsoluteURL(value) {
|
|||
}
|
||||
|
||||
function isBareIdentifier(value) {
|
||||
return value.charAt(0) !== "." && value.charAt(0) !== "/";
|
||||
return value.charAt(0) !== '.' && value.charAt(0) !== '/';
|
||||
}
|
||||
|
||||
function rewriteValue(/* StringLiteral */ node, dependencies) {
|
||||
|
@ -30,7 +30,7 @@ function rewriteValue(/* StringLiteral */ node, dependencies) {
|
|||
// "bare" identifier
|
||||
const match = bareIdentifierFormat.exec(node.value);
|
||||
const packageName = match[1];
|
||||
const file = match[2] || "";
|
||||
const file = match[2] || '';
|
||||
|
||||
warning(
|
||||
dependencies[packageName],
|
||||
|
@ -38,7 +38,7 @@ function rewriteValue(/* StringLiteral */ node, dependencies) {
|
|||
packageName
|
||||
);
|
||||
|
||||
const version = dependencies[packageName] || "latest";
|
||||
const version = dependencies[packageName] || 'latest';
|
||||
|
||||
node.value = `${origin}/${packageName}@${version}${file}?module`;
|
||||
} else {
|
||||
|
@ -51,16 +51,16 @@ function unpkgRewrite(dependencies = {}) {
|
|||
return {
|
||||
manipulateOptions(opts, parserOpts) {
|
||||
parserOpts.plugins.push(
|
||||
"dynamicImport",
|
||||
"exportDefaultFrom",
|
||||
"exportNamespaceFrom",
|
||||
"importMeta"
|
||||
'dynamicImport',
|
||||
'exportDefaultFrom',
|
||||
'exportNamespaceFrom',
|
||||
'importMeta'
|
||||
);
|
||||
},
|
||||
|
||||
visitor: {
|
||||
CallExpression(path) {
|
||||
if (path.node.callee.type !== "Import") {
|
||||
if (path.node.callee.type !== 'Import') {
|
||||
// Some other function call, not import();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const forge = require("node-forge");
|
||||
const invariant = require("invariant");
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const forge = require('node-forge');
|
||||
const invariant = require('invariant');
|
||||
|
||||
let secretKey;
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
invariant(
|
||||
process.env.PRIVATE_KEY,
|
||||
"Missing $PRIVATE_KEY environment variable"
|
||||
'Missing $PRIVATE_KEY environment variable'
|
||||
);
|
||||
|
||||
secretKey = {
|
||||
public: fs.readFileSync(
|
||||
path.resolve(__dirname, "../secret_key.pub"),
|
||||
"utf8"
|
||||
path.resolve(__dirname, '../secret_key.pub'),
|
||||
'utf8'
|
||||
),
|
||||
private: process.env.PRIVATE_KEY
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
exports.port = parseInt(process.env.PORT, 10) || 5000;
|
||||
|
||||
exports.origin =
|
||||
process.env.NODE_ENV === "production" || process.env.NODE_ENV === "test"
|
||||
? "https://unpkg.com"
|
||||
process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'test'
|
||||
? 'https://unpkg.com'
|
||||
: `http://localhost:${exports.port}`;
|
||||
|
||||
exports.registryURL =
|
||||
process.env.NPM_REGISTRY_URL || "https://registry.npmjs.org";
|
||||
process.env.NPM_REGISTRY_URL || 'https://registry.npmjs.org';
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
const createSearch = require("../createSearch");
|
||||
const createSearch = require('../createSearch');
|
||||
|
||||
describe("createSearch", () => {
|
||||
it("omits the trailing = for empty string values", () => {
|
||||
expect(createSearch({ a: "a", b: "" })).toEqual("?a=a&b");
|
||||
describe('createSearch', () => {
|
||||
it('omits the trailing = for empty string values', () => {
|
||||
expect(createSearch({ a: 'a', b: '' })).toEqual('?a=a&b');
|
||||
});
|
||||
|
||||
it("sorts keys", () => {
|
||||
expect(createSearch({ b: "b", a: "a", c: "c" })).toEqual("?a=a&b=b&c=c");
|
||||
it('sorts keys', () => {
|
||||
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", () => {
|
||||
expect(createSearch({})).toEqual("");
|
||||
it('returns an empty string when there are no params', () => {
|
||||
expect(createSearch({})).toEqual('');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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", () => {
|
||||
expect(getContentType("AUTHORS")).toBe("text/plain");
|
||||
expect(getContentType("CHANGES")).toBe("text/plain");
|
||||
expect(getContentType("LICENSE")).toBe("text/plain");
|
||||
expect(getContentType("Makefile")).toBe("text/plain");
|
||||
expect(getContentType("PATENTS")).toBe("text/plain");
|
||||
expect(getContentType("README")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for LICENSE|README|CHANGES|AUTHORS|Makefile', () => {
|
||||
expect(getContentType('AUTHORS')).toBe('text/plain');
|
||||
expect(getContentType('CHANGES')).toBe('text/plain');
|
||||
expect(getContentType('LICENSE')).toBe('text/plain');
|
||||
expect(getContentType('Makefile')).toBe('text/plain');
|
||||
expect(getContentType('PATENTS')).toBe('text/plain');
|
||||
expect(getContentType('README')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .*rc files", () => {
|
||||
expect(getContentType(".eslintrc")).toBe("text/plain");
|
||||
expect(getContentType(".babelrc")).toBe("text/plain");
|
||||
expect(getContentType(".anythingrc")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .*rc files', () => {
|
||||
expect(getContentType('.eslintrc')).toBe('text/plain');
|
||||
expect(getContentType('.babelrc')).toBe('text/plain');
|
||||
expect(getContentType('.anythingrc')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .git* files", () => {
|
||||
expect(getContentType(".gitignore")).toBe("text/plain");
|
||||
expect(getContentType(".gitanything")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .git* files', () => {
|
||||
expect(getContentType('.gitignore')).toBe('text/plain');
|
||||
expect(getContentType('.gitanything')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .*ignore files", () => {
|
||||
expect(getContentType(".eslintignore")).toBe("text/plain");
|
||||
expect(getContentType(".anythingignore")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .*ignore files', () => {
|
||||
expect(getContentType('.eslintignore')).toBe('text/plain');
|
||||
expect(getContentType('.anythingignore')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .ts files", () => {
|
||||
expect(getContentType("app.ts")).toBe("text/plain");
|
||||
expect(getContentType("app.d.ts")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .ts files', () => {
|
||||
expect(getContentType('app.ts')).toBe('text/plain');
|
||||
expect(getContentType('app.d.ts')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .flow files", () => {
|
||||
expect(getContentType("app.js.flow")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .flow files', () => {
|
||||
expect(getContentType('app.js.flow')).toBe('text/plain');
|
||||
});
|
||||
|
||||
it("gets a content type of text/plain for .lock files", () => {
|
||||
expect(getContentType("yarn.lock")).toBe("text/plain");
|
||||
it('gets a content type of text/plain for .lock files', () => {
|
||||
expect(getContentType('yarn.lock')).toBe('text/plain');
|
||||
});
|
||||
|
|
|
@ -1,80 +1,80 @@
|
|||
const parsePackageURL = require("../parsePackageURL");
|
||||
const parsePackageURL = require('../parsePackageURL');
|
||||
|
||||
describe("parsePackageURL", () => {
|
||||
it("parses plain packages", () => {
|
||||
expect(parsePackageURL("/history@1.0.0/umd/history.min.js")).toEqual({
|
||||
pathname: "/history@1.0.0/umd/history.min.js",
|
||||
search: "",
|
||||
describe('parsePackageURL', () => {
|
||||
it('parses plain packages', () => {
|
||||
expect(parsePackageURL('/history@1.0.0/umd/history.min.js')).toEqual({
|
||||
pathname: '/history@1.0.0/umd/history.min.js',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "history",
|
||||
packageVersion: "1.0.0",
|
||||
filename: "/umd/history.min.js"
|
||||
packageName: 'history',
|
||||
packageVersion: '1.0.0',
|
||||
filename: '/umd/history.min.js'
|
||||
});
|
||||
});
|
||||
|
||||
it("parses plain packages with a hyphen in the name", () => {
|
||||
expect(parsePackageURL("/query-string@5.0.0/index.js")).toEqual({
|
||||
pathname: "/query-string@5.0.0/index.js",
|
||||
search: "",
|
||||
it('parses plain packages with a hyphen in the name', () => {
|
||||
expect(parsePackageURL('/query-string@5.0.0/index.js')).toEqual({
|
||||
pathname: '/query-string@5.0.0/index.js',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "query-string",
|
||||
packageVersion: "5.0.0",
|
||||
filename: "/index.js"
|
||||
packageName: 'query-string',
|
||||
packageVersion: '5.0.0',
|
||||
filename: '/index.js'
|
||||
});
|
||||
});
|
||||
|
||||
it("parses plain packages with no version specified", () => {
|
||||
expect(parsePackageURL("/query-string/index.js")).toEqual({
|
||||
pathname: "/query-string/index.js",
|
||||
search: "",
|
||||
it('parses plain packages with no version specified', () => {
|
||||
expect(parsePackageURL('/query-string/index.js')).toEqual({
|
||||
pathname: '/query-string/index.js',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "query-string",
|
||||
packageVersion: "latest",
|
||||
filename: "/index.js"
|
||||
packageName: 'query-string',
|
||||
packageVersion: 'latest',
|
||||
filename: '/index.js'
|
||||
});
|
||||
});
|
||||
|
||||
it("parses plain packages with version spec", () => {
|
||||
expect(parsePackageURL("/query-string@>=4.0.0/index.js")).toEqual({
|
||||
pathname: "/query-string@>=4.0.0/index.js",
|
||||
search: "",
|
||||
it('parses plain packages with version spec', () => {
|
||||
expect(parsePackageURL('/query-string@>=4.0.0/index.js')).toEqual({
|
||||
pathname: '/query-string@>=4.0.0/index.js',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "query-string",
|
||||
packageVersion: ">=4.0.0",
|
||||
filename: "/index.js"
|
||||
packageName: 'query-string',
|
||||
packageVersion: '>=4.0.0',
|
||||
filename: '/index.js'
|
||||
});
|
||||
});
|
||||
|
||||
it("parses scoped packages", () => {
|
||||
expect(parsePackageURL("/@angular/router@4.3.3/src/index.d.ts")).toEqual({
|
||||
pathname: "/@angular/router@4.3.3/src/index.d.ts",
|
||||
search: "",
|
||||
it('parses scoped packages', () => {
|
||||
expect(parsePackageURL('/@angular/router@4.3.3/src/index.d.ts')).toEqual({
|
||||
pathname: '/@angular/router@4.3.3/src/index.d.ts',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "@angular/router",
|
||||
packageVersion: "4.3.3",
|
||||
filename: "/src/index.d.ts"
|
||||
packageName: '@angular/router',
|
||||
packageVersion: '4.3.3',
|
||||
filename: '/src/index.d.ts'
|
||||
});
|
||||
});
|
||||
|
||||
it("parses package names with a period in them", () => {
|
||||
expect(parsePackageURL("/index.js")).toEqual({
|
||||
pathname: "/index.js",
|
||||
search: "",
|
||||
it('parses package names with a period in them', () => {
|
||||
expect(parsePackageURL('/index.js')).toEqual({
|
||||
pathname: '/index.js',
|
||||
search: '',
|
||||
query: {},
|
||||
packageName: "index.js",
|
||||
packageVersion: "latest",
|
||||
filename: ""
|
||||
packageName: 'index.js',
|
||||
packageVersion: 'latest',
|
||||
filename: ''
|
||||
});
|
||||
});
|
||||
|
||||
it("parses valid query parameters", () => {
|
||||
expect(parsePackageURL("/history?main=browser")).toEqual({
|
||||
pathname: "/history",
|
||||
search: "?main=browser",
|
||||
query: { main: "browser" },
|
||||
packageName: "history",
|
||||
packageVersion: "latest",
|
||||
filename: ""
|
||||
it('parses valid query parameters', () => {
|
||||
expect(parsePackageURL('/history?main=browser')).toEqual({
|
||||
pathname: '/history',
|
||||
search: '?main=browser',
|
||||
query: { main: 'browser' },
|
||||
packageName: 'history',
|
||||
packageVersion: 'latest',
|
||||
filename: ''
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
function addLeadingSlash(name) {
|
||||
return name.charAt(0) === "/" ? name : "/" + name;
|
||||
return name.charAt(0) === '/' ? name : '/' + name;
|
||||
}
|
||||
|
||||
module.exports = addLeadingSlash;
|
||||
|
|
|
@ -3,9 +3,9 @@ function bufferStream(stream) {
|
|||
const chunks = [];
|
||||
|
||||
stream
|
||||
.on("error", reject)
|
||||
.on("data", chunk => chunks.push(chunk))
|
||||
.on("end", () => resolve(Buffer.concat(chunks)));
|
||||
.on('error', reject)
|
||||
.on('data', chunk => chunks.push(chunk))
|
||||
.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const redis = require("redis");
|
||||
const redis = require('redis');
|
||||
|
||||
redis.debug_mode = process.env.DEBUG_REDIS != null;
|
||||
|
||||
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;
|
||||
|
|
|
@ -3,14 +3,14 @@ function createSearch(query) {
|
|||
const params = keys.reduce(
|
||||
(memo, key) =>
|
||||
memo.concat(
|
||||
query[key] === ""
|
||||
query[key] === ''
|
||||
? key // Omit the trailing "=" from key=
|
||||
: `${key}=${encodeURIComponent(query[key])}`
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
return params.length ? `?${params.join("&")}` : "";
|
||||
return params.length ? `?${params.join('&')}` : '';
|
||||
}
|
||||
|
||||
module.exports = createSearch;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
const redis = require("redis");
|
||||
const redis = require('redis');
|
||||
|
||||
redis.debug_mode = process.env.DEBUG_REDIS != null;
|
||||
|
||||
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;
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
const url = require("url");
|
||||
const https = require("https");
|
||||
const gunzip = require("gunzip-maybe");
|
||||
const tar = require("tar-stream");
|
||||
const url = require('url');
|
||||
const https = require('https');
|
||||
const gunzip = require('gunzip-maybe');
|
||||
const tar = require('tar-stream');
|
||||
|
||||
const bufferStream = require("./bufferStream");
|
||||
const agent = require("./registryAgent");
|
||||
const logging = require("./logging");
|
||||
const bufferStream = require('./bufferStream');
|
||||
const agent = require('./registryAgent');
|
||||
const logging = require('./logging');
|
||||
|
||||
function fetchNpmPackage(packageConfig) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const tarballURL = packageConfig.dist.tarball;
|
||||
|
||||
logging.debug(
|
||||
"Fetching package for %s from %s",
|
||||
'Fetching package for %s from %s',
|
||||
packageConfig.name,
|
||||
tarballURL
|
||||
);
|
||||
|
@ -31,7 +31,7 @@ function fetchNpmPackage(packageConfig) {
|
|||
} else {
|
||||
bufferStream(res).then(data => {
|
||||
const spec = `${packageConfig.name}@${packageConfig.version}`;
|
||||
const content = data.toString("utf-8");
|
||||
const content = data.toString('utf-8');
|
||||
const error = new Error(
|
||||
`Failed to fetch tarball for ${spec}\nstatus: ${
|
||||
res.statusCode
|
||||
|
@ -42,7 +42,7 @@ function fetchNpmPackage(packageConfig) {
|
|||
});
|
||||
}
|
||||
})
|
||||
.on("error", reject);
|
||||
.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const url = require("url");
|
||||
const https = require("https");
|
||||
const url = require('url');
|
||||
const https = require('https');
|
||||
|
||||
const serverConfig = require("../serverConfig");
|
||||
const bufferStream = require("./bufferStream");
|
||||
const agent = require("./registryAgent");
|
||||
const logging = require("./logging");
|
||||
const serverConfig = require('../serverConfig');
|
||||
const bufferStream = require('./bufferStream');
|
||||
const agent = require('./registryAgent');
|
||||
const logging = require('./logging');
|
||||
|
||||
function parseJSON(res) {
|
||||
return bufferStream(res).then(JSON.parse);
|
||||
|
@ -13,13 +13,13 @@ function parseJSON(res) {
|
|||
function fetchNpmPackageInfo(packageName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const encodedPackageName =
|
||||
packageName.charAt(0) === "@"
|
||||
packageName.charAt(0) === '@'
|
||||
? `@${encodeURIComponent(packageName.substring(1))}`
|
||||
: encodeURIComponent(packageName);
|
||||
|
||||
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 options = {
|
||||
|
@ -27,7 +27,7 @@ function fetchNpmPackageInfo(packageName) {
|
|||
hostname: hostname,
|
||||
path: pathname,
|
||||
headers: {
|
||||
Accept: "application/json"
|
||||
Accept: 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,7 @@ function fetchNpmPackageInfo(packageName) {
|
|||
resolve(null);
|
||||
} else {
|
||||
bufferStream(res).then(data => {
|
||||
const content = data.toString("utf-8");
|
||||
const content = data.toString('utf-8');
|
||||
const error = new Error(
|
||||
`Failed to fetch info for ${packageName}\nstatus: ${
|
||||
res.statusCode
|
||||
|
@ -50,7 +50,7 @@ function fetchNpmPackageInfo(packageName) {
|
|||
});
|
||||
}
|
||||
})
|
||||
.on("error", reject);
|
||||
.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
const mime = require("mime");
|
||||
const mime = require('mime');
|
||||
|
||||
mime.define({
|
||||
"text/plain": [
|
||||
"authors",
|
||||
"changes",
|
||||
"license",
|
||||
"makefile",
|
||||
"patents",
|
||||
"readme",
|
||||
"ts",
|
||||
"flow"
|
||||
'text/plain': [
|
||||
'authors',
|
||||
'changes',
|
||||
'license',
|
||||
'makefile',
|
||||
'patents',
|
||||
'readme',
|
||||
'ts',
|
||||
'flow'
|
||||
]
|
||||
});
|
||||
|
||||
const textFiles = /\/?(\.[a-z]*rc|\.git[a-z]*|\.[a-z]*ignore|\.lock)$/i;
|
||||
|
||||
function getContentType(file) {
|
||||
return textFiles.test(file) ? "text/plain" : mime.lookup(file);
|
||||
return textFiles.test(file) ? 'text/plain' : mime.lookup(file);
|
||||
}
|
||||
|
||||
module.exports = getContentType;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
function getContentTypeHeader(type) {
|
||||
return type === "application/javascript" ? type + "; charset=utf-8" : type;
|
||||
return type === 'application/javascript' ? type + '; charset=utf-8' : type;
|
||||
}
|
||||
|
||||
module.exports = getContentTypeHeader;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const SRIToolbox = require("sri-toolbox");
|
||||
const SRIToolbox = require('sri-toolbox');
|
||||
|
||||
function getIntegrity(data) {
|
||||
return SRIToolbox.generate({ algorithms: ["sha384"] }, data);
|
||||
return SRIToolbox.generate({ algorithms: ['sha384'] }, data);
|
||||
}
|
||||
|
||||
module.exports = getIntegrity;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const cache = require("./cache");
|
||||
const fetchNpmPackageInfo = require("./fetchNpmPackageInfo");
|
||||
const cache = require('./cache');
|
||||
const fetchNpmPackageInfo = require('./fetchNpmPackageInfo');
|
||||
|
||||
const notFound = 0;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const db = require("./data");
|
||||
const db = require('./data');
|
||||
|
||||
function incrementCounter(counter, key, by = 1) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const validateNpmPackageName = require("validate-npm-package-name");
|
||||
const validateNpmPackageName = require('validate-npm-package-name');
|
||||
|
||||
function isValidPackageName(packageName) {
|
||||
return validateNpmPackageName(packageName).errors == null;
|
||||
|
|
|
@ -4,11 +4,11 @@ function noop() {}
|
|||
|
||||
let debug, info, warn;
|
||||
|
||||
if (process.env.LOG_LEVEL === "none") {
|
||||
if (process.env.LOG_LEVEL === 'none') {
|
||||
debug = info = warn = noop;
|
||||
} else if (process.env.LOG_LEVEL === "debug") {
|
||||
} else if (process.env.LOG_LEVEL === 'debug') {
|
||||
debug = info = warn = log;
|
||||
} else if (process.env.LOG_LEVEL === "warn") {
|
||||
} else if (process.env.LOG_LEVEL === 'warn') {
|
||||
debug = info = noop;
|
||||
warn = log;
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const url = require("url");
|
||||
const url = require('url');
|
||||
|
||||
const packageURLFormat = /^\/((?:@[^/@]+\/)?[^/@]+)(?:@([^/]+))?(\/.*)?$/;
|
||||
|
||||
|
@ -11,7 +11,7 @@ function decodeParam(param) {
|
|||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
|
||||
function parsePackageURL(originalURL) {
|
||||
|
@ -24,13 +24,13 @@ function parsePackageURL(originalURL) {
|
|||
}
|
||||
|
||||
const packageName = match[1];
|
||||
const packageVersion = decodeParam(match[2]) || "latest";
|
||||
const packageVersion = decodeParam(match[2]) || 'latest';
|
||||
const filename = decodeParam(match[3]);
|
||||
|
||||
return {
|
||||
// If the URL is /@scope/name@version/file.js?main=browser:
|
||||
pathname, // /@scope/name@version/path.js
|
||||
search: search || "", // ?main=browser
|
||||
search: search || '', // ?main=browser
|
||||
query, // { main: 'browser' }
|
||||
packageName, // @scope/name
|
||||
packageVersion, // version
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const https = require("https");
|
||||
const https = require('https');
|
||||
|
||||
const agent = new https.Agent({
|
||||
keepAlive: true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const React = require("react");
|
||||
const ReactDOMServer = require("react-dom/server");
|
||||
const React = require('react');
|
||||
const ReactDOMServer = require('react-dom/server');
|
||||
|
||||
const doctype = "<!DOCTYPE html>";
|
||||
const doctype = '<!DOCTYPE html>';
|
||||
|
||||
function renderPage(page, props) {
|
||||
const element = React.createElement(page, props);
|
||||
|
|
|
@ -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) {
|
||||
const dependencies = Object.assign(
|
||||
|
|
Loading…
Reference in New Issue