style: enable scratch/es6 lint rules

This commit is contained in:
Christopher Willis-Ford 2024-01-17 12:40:27 -08:00
parent 2b5b8a371c
commit c2fa2fedd5
9 changed files with 205 additions and 207 deletions

View file

@ -1,4 +1,4 @@
module.exports = { module.exports = {
extends: ['scratch', 'scratch/node'], extends: ['scratch', 'scratch/node', 'scratch/es6'],
plugins: ['json'] plugins: ['json']
}; };

View file

@ -2,15 +2,15 @@
const https = require('https'); const https = require('https');
let environment = process.env.SCRATCH_ENV || 'unknown environment'; const environment = process.env.SCRATCH_ENV || 'unknown environment';
let branch = process.env.CIRCLE_BRANCH || 'unknown branch'; const branch = process.env.CIRCLE_BRANCH || 'unknown branch';
let urlEng = process.env.SLACK_WEBHOOK_ENGINEERING; const urlEng = process.env.SLACK_WEBHOOK_ENGINEERING;
let urlMod = process.env.SLACK_WEBHOOK_MODS; const urlMod = process.env.SLACK_WEBHOOK_MODS;
let urlNotifications = process.env.SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS; const urlNotifications = process.env.SLACK_WEBHOOK_CIRCLECI_NOTIFICATIONS;
let announcement = {text: `scratch-www has deployed branch ${branch} to ${environment}.`}; const announcement = {text: `scratch-www has deployed branch ${branch} to ${environment}.`};
const options = { const options = {
method: 'POST', method: 'POST',
@ -20,11 +20,11 @@ const options = {
}; };
const postMessage = (url, message, channelName) => { const postMessage = (url, message, channelName) => {
let data = JSON.stringify(message); const data = JSON.stringify(message);
const req = https.request(url, options, res => { const req = https.request(url, options, res => {
console.log(`statusCode: ${res.statusCode}`); // eslint-disable-line no-console console.log(`statusCode: ${res.statusCode}`); // eslint-disable-line no-console
if (res.statusCode === 200) { if (res.statusCode === 200) {
process.stdout.write(`announced to ${channelName}\n` + JSON.stringify(message) + '\n'); process.stdout.write(`announced to ${channelName}\n${JSON.stringify(message)}\n`);
} else { } else {
process.stdout.write(`FAILED to announce to slack`); process.stdout.write(`FAILED to announce to slack`);
} }

View file

@ -1,16 +1,16 @@
var async = require('async'); const async = require('async');
var defaults = require('lodash.defaults'); const defaults = require('lodash.defaults');
var fastlyConfig = require('./lib/fastly-config-methods'); const fastlyConfig = require('./lib/fastly-config-methods');
const languages = require('scratch-l10n').default; const languages = require('scratch-l10n').default;
var routeJson = require('../src/routes.json'); const routeJson = require('../src/routes.json');
const FASTLY_SERVICE_ID = process.env.FASTLY_SERVICE_ID || ''; const FASTLY_SERVICE_ID = process.env.FASTLY_SERVICE_ID || '';
const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || ''; const S3_BUCKET_NAME = process.env.S3_BUCKET_NAME || '';
var fastly = require('./lib/fastly-extended')(process.env.FASTLY_API_KEY, FASTLY_SERVICE_ID); const fastly = require('./lib/fastly-extended')(process.env.FASTLY_API_KEY, FASTLY_SERVICE_ID);
var extraAppRoutes = [ const extraAppRoutes = [
// Homepage with querystring. // Homepage with querystring.
// TODO: Should this be added for every route? // TODO: Should this be added for every route?
'/\\?', '/\\?',
@ -18,18 +18,18 @@ var extraAppRoutes = [
'/[^/]*.html$' '/[^/]*.html$'
]; ];
var routes = routeJson.map(function (route) { const routes = routeJson.map(
return defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route); route => defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route)
}); );
async.auto({ async.auto({
version: function (cb) { version: function (cb) {
fastly.getLatestActiveVersion(function (err, response) { fastly.getLatestActiveVersion((err, response) => {
if (err) return cb(err); if (err) return cb(err);
// Validate latest version before continuing // Validate latest version before continuing
if (response.active || response.locked) { if (response.active || response.locked) {
fastly.cloneVersion(response.number, function (e, resp) { fastly.cloneVersion(response.number, (e, resp) => {
if (e) return cb('Failed to clone latest version: ' + e); if (e) return cb(`Failed to clone latest version: ${e}`);
cb(null, resp.number); cb(null, resp.number);
}); });
} else { } else {
@ -40,40 +40,40 @@ async.auto({
recvCustomVCL: ['version', function (results, cb) { recvCustomVCL: ['version', function (results, cb) {
// For all the routes in routes.json, construct a varnish-style regex that matches // For all the routes in routes.json, construct a varnish-style regex that matches
// on any of those route conditions. // on any of those route conditions.
var notPassStatement = fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname); const notPassStatement = fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname);
// For a non-pass condition, point backend at s3 // For a non-pass condition, point backend at s3
var recvCondition = '' + const recvCondition = `${'' +
'if (' + notPassStatement + ') {\n' + 'if ('}${notPassStatement}) {\n` +
' set req.backend = F_s3;\n' + ` set req.backend = F_s3;\n` +
' set req.http.host = "' + S3_BUCKET_NAME + '";\n' + ` set req.http.host = "${S3_BUCKET_NAME}";\n` +
'} else {\n' + `} else {\n` +
' if (!req.http.Fastly-FF) {\n' + ` if (!req.http.Fastly-FF) {\n` +
' if (req.http.X-Forwarded-For) {\n' + ` if (req.http.X-Forwarded-For) {\n` +
' set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For ", " client.ip;\n' + ` set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For ", " client.ip;\n` +
' } else {\n' + ` } else {\n` +
' set req.http.Fastly-Temp-XFF = client.ip;\n' + ` set req.http.Fastly-Temp-XFF = client.ip;\n` +
' }\n' + ` }\n` +
' } else {\n' + ` } else {\n` +
' set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For;\n' + ` set req.http.Fastly-Temp-XFF = req.http.X-Forwarded-For;\n` +
' }\n' + ` }\n` +
' set req.grace = 60s;\n' + ` set req.grace = 60s;\n` +
' if (req.http.Cookie:scratchlanguage) {\n' + ` if (req.http.Cookie:scratchlanguage) {\n` +
' set req.http.Accept-Language = req.http.Cookie:scratchlanguage;\n' + ` set req.http.Accept-Language = req.http.Cookie:scratchlanguage;\n` +
' } else {\n' + ` } else {\n` +
' set req.http.Accept-Language = accept.language_lookup("' + ` set req.http.Accept-Language = accept.language_lookup("${
Object.keys(languages).join(':') + '", ' + Object.keys(languages).join(':')}", ` +
'"en", ' + `"en", ` +
'std.tolower(req.http.Accept-Language)' + `std.tolower(req.http.Accept-Language)` +
');\n' + `);\n` +
' }\n' + ` }\n` +
' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' + ` if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ` +
'!req.http.Cookie:scratchsessionsid) {\n' + `!req.http.Cookie:scratchsessionsid) {\n` +
' set req.http.Cookie = "scratchlanguage=" req.http.Cookie:scratchlanguage;\n' + ` set req.http.Cookie = "scratchlanguage=" req.http.Cookie:scratchlanguage;\n` +
' } else {\n' + ` } else {\n` +
' return(pass);\n' + ` return(pass);\n` +
' }\n' + ` }\n` +
'}\n'; `}\n`;
fastly.setCustomVCL( fastly.setCustomVCL(
@ -84,48 +84,48 @@ async.auto({
); );
}], }],
fetchCustomVCL: ['version', function (results, cb) { fetchCustomVCL: ['version', function (results, cb) {
var passStatement = fastlyConfig.negateConditionStatement( const passStatement = fastlyConfig.negateConditionStatement(
fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname) fastlyConfig.getAppRouteCondition('../build/*', routes, extraAppRoutes, __dirname)
); );
var ttlCondition = fastlyConfig.setResponseTTL(passStatement); const ttlCondition = fastlyConfig.setResponseTTL(passStatement);
fastly.setCustomVCL(results.version, 'fetch-condition', ttlCondition, cb); fastly.setCustomVCL(results.version, 'fetch-condition', ttlCondition, cb);
}], }],
appRouteRequestConditions: ['version', function (results, cb) { appRouteRequestConditions: ['version', function (results, cb) {
var conditions = {}; const conditions = {};
async.forEachOf(routes, function (route, id, cb2) { async.forEachOf(routes, (route, id, cb2) => {
var condition = { const condition = {
name: fastlyConfig.getConditionNameForRoute(route, 'request'), name: fastlyConfig.getConditionNameForRoute(route, 'request'),
statement: 'req.url.path ~ "' + route.pattern + '"', statement: `req.url.path ~ "${route.pattern}"`,
type: 'REQUEST', type: 'REQUEST',
// Priority needs to be > 1 to not interact with http->https redirect // Priority needs to be > 1 to not interact with http->https redirect
priority: 10 + id priority: 10 + id
}; };
fastly.setCondition(results.version, condition, function (err, response) { fastly.setCondition(results.version, condition, (err, response) => {
if (err) return cb2(err); if (err) return cb2(err);
conditions[id] = response; conditions[id] = response;
cb2(null, response); cb2(null, response);
}); });
}, function (err) { }, err => {
if (err) return cb(err); if (err) return cb(err);
cb(null, conditions); cb(null, conditions);
}); });
}], }],
appRouteHeaders: ['version', 'appRouteRequestConditions', function (results, cb) { appRouteHeaders: ['version', 'appRouteRequestConditions', function (results, cb) {
var headers = {}; const headers = {};
async.forEachOf(routes, function (route, id, cb2) { async.forEachOf(routes, (route, id, cb2) => {
if (route.redirect) { if (route.redirect) {
async.auto({ async.auto({
responseCondition: function (cb3) { responseCondition: function (cb3) {
var condition = { const condition = {
name: fastlyConfig.getConditionNameForRoute(route, 'response'), name: fastlyConfig.getConditionNameForRoute(route, 'response'),
statement: 'req.url.path ~ "' + route.pattern + '"', statement: `req.url.path ~ "${route.pattern}"`,
type: 'RESPONSE', type: 'RESPONSE',
priority: id priority: id
}; };
fastly.setCondition(results.version, condition, cb3); fastly.setCondition(results.version, condition, cb3);
}, },
responseObject: function (cb3) { responseObject: function (cb3) {
var responseObject = { const responseObject = {
name: fastlyConfig.getResponseNameForRoute(route), name: fastlyConfig.getResponseNameForRoute(route),
status: 301, status: 301,
response: 'Moved Permanently', response: 'Moved Permanently',
@ -134,40 +134,40 @@ async.auto({
fastly.setResponseObject(results.version, responseObject, cb3); fastly.setResponseObject(results.version, responseObject, cb3);
}, },
redirectHeader: ['responseCondition', function (redirectResults, cb3) { redirectHeader: ['responseCondition', function (redirectResults, cb3) {
var header = { const header = {
name: fastlyConfig.getHeaderNameForRoute(route), name: fastlyConfig.getHeaderNameForRoute(route),
action: 'set', action: 'set',
ignore_if_set: 0, ignore_if_set: 0,
type: 'RESPONSE', type: 'RESPONSE',
dst: 'http.Location', dst: 'http.Location',
src: '"' + route.redirect + '"', src: `"${route.redirect}"`,
response_condition: redirectResults.responseCondition.name response_condition: redirectResults.responseCondition.name
}; };
fastly.setFastlyHeader(results.version, header, cb3); fastly.setFastlyHeader(results.version, header, cb3);
}] }]
}, function (err, redirectResults) { }, (err, redirectResults) => {
if (err) return cb2(err); if (err) return cb2(err);
headers[id] = redirectResults.redirectHeader; headers[id] = redirectResults.redirectHeader;
cb2(null, redirectResults); cb2(null, redirectResults);
}); });
} else { } else {
var header = { const header = {
name: fastlyConfig.getHeaderNameForRoute(route, 'request'), name: fastlyConfig.getHeaderNameForRoute(route, 'request'),
action: 'set', action: 'set',
ignore_if_set: 0, ignore_if_set: 0,
type: 'REQUEST', type: 'REQUEST',
dst: 'url', dst: 'url',
src: '"/' + route.name + '.html"', src: `"/${route.name}.html"`,
request_condition: results.appRouteRequestConditions[id].name, request_condition: results.appRouteRequestConditions[id].name,
priority: 10 priority: 10
}; };
fastly.setFastlyHeader(results.version, header, function (err, response) { fastly.setFastlyHeader(results.version, header, (err, response) => {
if (err) return cb2(err); if (err) return cb2(err);
headers[id] = response; headers[id] = response;
cb2(null, response); cb2(null, response);
}); });
} }
}, function (err) { }, err => {
if (err) return cb(err); if (err) return cb(err);
cb(null, headers); cb(null, headers);
}); });
@ -175,7 +175,7 @@ async.auto({
tipbarRedirectHeaders: ['version', function (results, cb) { tipbarRedirectHeaders: ['version', function (results, cb) {
async.auto({ async.auto({
requestCondition: function (cb2) { requestCondition: function (cb2) {
var condition = { const condition = {
name: 'routes/?tip_bar= (request)', name: 'routes/?tip_bar= (request)',
statement: 'req.url ~ "\\?tip_bar="', statement: 'req.url ~ "\\?tip_bar="',
type: 'REQUEST', type: 'REQUEST',
@ -184,7 +184,7 @@ async.auto({
fastly.setCondition(results.version, condition, cb2); fastly.setCondition(results.version, condition, cb2);
}, },
responseCondition: function (cb2) { responseCondition: function (cb2) {
var condition = { const condition = {
name: 'routes/?tip_bar= (response)', name: 'routes/?tip_bar= (response)',
statement: 'req.url ~ "\\?tip_bar="', statement: 'req.url ~ "\\?tip_bar="',
type: 'RESPONSE', type: 'RESPONSE',
@ -193,7 +193,7 @@ async.auto({
fastly.setCondition(results.version, condition, cb2); fastly.setCondition(results.version, condition, cb2);
}, },
responseObject: ['requestCondition', function (redirectResults, cb2) { responseObject: ['requestCondition', function (redirectResults, cb2) {
var responseObject = { const responseObject = {
name: 'redirects/?tip_bar=', name: 'redirects/?tip_bar=',
status: 301, status: 301,
response: 'Moved Permanently', response: 'Moved Permanently',
@ -202,7 +202,7 @@ async.auto({
fastly.setResponseObject(results.version, responseObject, cb2); fastly.setResponseObject(results.version, responseObject, cb2);
}], }],
redirectHeader: ['responseCondition', function (redirectResults, cb2) { redirectHeader: ['responseCondition', function (redirectResults, cb2) {
var header = { const header = {
name: 'redirects/?tip_bar=', name: 'redirects/?tip_bar=',
action: 'set', action: 'set',
ignore_if_set: 0, ignore_if_set: 0,
@ -213,7 +213,7 @@ async.auto({
}; };
fastly.setFastlyHeader(results.version, header, cb2); fastly.setFastlyHeader(results.version, header, cb2);
}] }]
}, function (err, redirectResults) { }, (err, redirectResults) => {
if (err) return cb(err); if (err) return cb(err);
cb(null, redirectResults); cb(null, redirectResults);
}); });
@ -221,7 +221,7 @@ async.auto({
embedRedirectHeaders: ['version', function (results, cb) { embedRedirectHeaders: ['version', function (results, cb) {
async.auto({ async.auto({
requestCondition: function (cb2) { requestCondition: function (cb2) {
var condition = { const condition = {
name: 'routes/projects/embed (request)', name: 'routes/projects/embed (request)',
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"', statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
type: 'REQUEST', type: 'REQUEST',
@ -230,7 +230,7 @@ async.auto({
fastly.setCondition(results.version, condition, cb2); fastly.setCondition(results.version, condition, cb2);
}, },
responseCondition: function (cb2) { responseCondition: function (cb2) {
var condition = { const condition = {
name: 'routes/projects/embed (response)', name: 'routes/projects/embed (response)',
statement: 'req.url.path ~ "^/projects/embed/(\\d+)"', statement: 'req.url.path ~ "^/projects/embed/(\\d+)"',
type: 'RESPONSE', type: 'RESPONSE',
@ -239,7 +239,7 @@ async.auto({
fastly.setCondition(results.version, condition, cb2); fastly.setCondition(results.version, condition, cb2);
}, },
responseObject: ['requestCondition', function (redirectResults, cb2) { responseObject: ['requestCondition', function (redirectResults, cb2) {
var responseObject = { const responseObject = {
name: 'redirects/projects/embed', name: 'redirects/projects/embed',
status: 301, status: 301,
response: 'Moved Permanently', response: 'Moved Permanently',
@ -248,7 +248,7 @@ async.auto({
fastly.setResponseObject(results.version, responseObject, cb2); fastly.setResponseObject(results.version, responseObject, cb2);
}], }],
redirectHeader: ['responseCondition', function (redirectResults, cb2) { redirectHeader: ['responseCondition', function (redirectResults, cb2) {
var header = { const header = {
name: 'redirects/projects/embed', name: 'redirects/projects/embed',
action: 'set', action: 'set',
ignore_if_set: 0, ignore_if_set: 0,
@ -259,19 +259,19 @@ async.auto({
}; };
fastly.setFastlyHeader(results.version, header, cb2); fastly.setFastlyHeader(results.version, header, cb2);
}] }]
}, function (err, redirectResults) { }, (err, redirectResults) => {
if (err) return cb(err); if (err) return cb(err);
cb(null, redirectResults); cb(null, redirectResults);
}); });
}] }]
}, function (err, results) { }, (err, results) => {
if (err) throw new Error(err); if (err) throw new Error(err);
if (process.env.FASTLY_ACTIVATE_CHANGES) { if (process.env.FASTLY_ACTIVATE_CHANGES) {
fastly.activateVersion(results.version, function (e, resp) { fastly.activateVersion(results.version, (e, resp) => {
if (e) throw new Error(e); if (e) throw new Error(e);
process.stdout.write('Successfully configured and activated version ' + resp.number + '\n'); process.stdout.write(`Successfully configured and activated version ${resp.number}\n`);
// purge static-assets using surrogate key // purge static-assets using surrogate key
fastly.purgeKey(FASTLY_SERVICE_ID, 'static-assets', function (error) { fastly.purgeKey(FASTLY_SERVICE_ID, 'static-assets', error => {
if (error) throw new Error(error); if (error) throw new Error(error);
process.stdout.write('Purged static assets.\n'); process.stdout.write('Purged static assets.\n');
}); });

View file

@ -1,19 +1,19 @@
var glob = require('glob'); const glob = require('glob');
var path = require('path'); const path = require('path');
var FastlyConfigMethods = { const FastlyConfigMethods = {
/* /*
* Given the relative path to the static directory, return an array of * Given the relative path to the static directory, return an array of
* patterns matching the files and directories there. * patterns matching the files and directories there.
*/ */
getStaticPaths: function (rootDir, pathToStatic) { getStaticPaths: function (rootDir, pathToStatic) {
var staticPaths = glob.sync(path.resolve(rootDir, pathToStatic)); const staticPaths = glob.sync(path.resolve(rootDir, pathToStatic));
return staticPaths.filter(function (pathName) { return staticPaths.filter(pathName =>
// Exclude view html, resolve everything else in the build // Exclude view html, resolve everything else in the build
return path.extname(pathName) !== '.html'; path.extname(pathName) !== '.html'
}).map(function (pathName) { ).map(pathName => {
// Reduce absolute path to relative paths like '/js' // Reduce absolute path to relative paths like '/js'
var base = path.dirname(path.resolve(rootDir, pathToStatic)); const base = path.dirname(path.resolve(rootDir, pathToStatic));
return pathName.replace(base, '') + (path.extname(pathName) ? '' : '/'); return pathName.replace(base, '') + (path.extname(pathName) ? '' : '/');
}); });
}, },
@ -23,8 +23,8 @@ var FastlyConfigMethods = {
* the express route and a static view file associated with the route * the express route and a static view file associated with the route
*/ */
getViewPaths: function (routes) { getViewPaths: function (routes) {
return routes.reduce(function (paths, route) { return routes.reduce((paths, route) => {
var p = route.routeAlias || route.pattern; const p = route.routeAlias || route.pattern;
if (paths.indexOf(p) === -1) { if (paths.indexOf(p) === -1) {
paths.push(p); paths.push(p);
} }
@ -48,16 +48,16 @@ var FastlyConfigMethods = {
* string suitable for a Fastly condition * string suitable for a Fastly condition
*/ */
pathsToCondition: function (paths) { pathsToCondition: function (paths) {
return 'req.url~"^(' + paths.reduce(function (conditionString, pattern) { return `req.url~"^(${
return conditionString + (conditionString ? '|' : '') + pattern; paths.reduce((conditionString, pattern) => conditionString + (conditionString ? '|' : '') + pattern, '')
}, '') + ')"'; })"`;
}, },
/* /*
* Helper method to NOT a condition statement * Helper method to NOT a condition statement
*/ */
negateConditionStatement: function (statement) { negateConditionStatement: function (statement) {
return '!(' + statement + ')'; return `!(${statement})`;
}, },
/* /*
@ -65,23 +65,23 @@ var FastlyConfigMethods = {
* fastly condition to match req.url * fastly condition to match req.url
*/ */
getAppRouteCondition: function (pathToStatic, routes, additionalPaths, rootDir) { getAppRouteCondition: function (pathToStatic, routes, additionalPaths, rootDir) {
var staticPaths = FastlyConfigMethods.getStaticPaths(rootDir, pathToStatic); const staticPaths = FastlyConfigMethods.getStaticPaths(rootDir, pathToStatic);
var viewPaths = FastlyConfigMethods.getViewPaths(routes); const viewPaths = FastlyConfigMethods.getViewPaths(routes);
var allPaths = [].concat(staticPaths, viewPaths, additionalPaths); const allPaths = [].concat(staticPaths, viewPaths, additionalPaths);
return FastlyConfigMethods.pathsToCondition(allPaths); return FastlyConfigMethods.pathsToCondition(allPaths);
}, },
getConditionNameForRoute: function (route, type) { getConditionNameForRoute: function (route, type) {
return 'routes/' + route.pattern + ' (' + type + ')'; return `routes/${route.pattern} (${type})`;
}, },
getHeaderNameForRoute: function (route) { getHeaderNameForRoute: function (route) {
if (route.name) return 'rewrites/' + route.name; if (route.name) return `rewrites/${route.name}`;
if (route.redirect) return 'redirects/' + route.pattern; if (route.redirect) return `redirects/${route.pattern}`;
}, },
getResponseNameForRoute: function (route) { getResponseNameForRoute: function (route) {
return 'redirects/' + route.pattern; return `redirects/${route.pattern}`;
}, },
/* /*
@ -91,19 +91,19 @@ var FastlyConfigMethods = {
* @param {string} condition condition under which the response should be set * @param {string} condition condition under which the response should be set
*/ */
setResponseTTL: function (condition) { setResponseTTL: function (condition) {
return '' + return `${'' +
'if (' + condition + ') {\n' + 'if ('}${condition}) {\n` +
' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' + ` if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ` +
'!req.http.Cookie:scratchsessionsid) {\n' + `!req.http.Cookie:scratchsessionsid) {\n` +
' set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n' + ` set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n` +
' unset beresp.http.set-cookie;\n' + ` unset beresp.http.set-cookie;\n` +
' return(deliver);\n' + ` return(deliver);\n` +
' } else {\n' + ` } else {\n` +
' set beresp.ttl = 0s;\n' + ` set beresp.ttl = 0s;\n` +
' set beresp.grace = 0s;\n' + ` set beresp.grace = 0s;\n` +
' return(pass);\n' + ` return(pass);\n` +
' }\n' + ` }\n` +
'}\n'; `}\n`;
} }
}; };

View file

@ -1,4 +1,4 @@
var Fastly = require('fastly'); const Fastly = require('fastly');
/* /*
* Fastly library extended to allow configuration for a particular service * Fastly library extended to allow configuration for a particular service
@ -8,7 +8,7 @@ var Fastly = require('fastly');
* @param {string} Service id * @param {string} Service id
*/ */
module.exports = function (apiKey, serviceId) { module.exports = function (apiKey, serviceId) {
var fastly = Fastly(apiKey); const fastly = Fastly(apiKey);
fastly.serviceId = serviceId; fastly.serviceId = serviceId;
/* /*
@ -20,7 +20,7 @@ module.exports = function (apiKey, serviceId) {
* @return {string} * @return {string}
*/ */
fastly.getFastlyAPIPrefix = function (servId, version) { fastly.getFastlyAPIPrefix = function (servId, version) {
return '/service/' + encodeURIComponent(servId) + '/version/' + version; return `/service/${encodeURIComponent(servId)}/version/${version}`;
}; };
/* /*
@ -32,12 +32,12 @@ module.exports = function (apiKey, serviceId) {
if (!this.serviceId) { if (!this.serviceId) {
return cb('Failed to get latest version. No serviceId configured'); return cb('Failed to get latest version. No serviceId configured');
} }
var url = '/service/' + encodeURIComponent(this.serviceId) + '/version'; const url = `/service/${encodeURIComponent(this.serviceId)}/version`;
this.request('GET', url, function (err, versions) { this.request('GET', url, (err, versions) => {
if (err) { if (err) {
return cb('Failed to fetch versions: ' + err); return cb(`Failed to fetch versions: ${err}`);
} }
var latestVersion = versions.reduce((latestActiveSoFar, cur) => { const latestVersion = versions.reduce((latestActiveSoFar, cur) => {
// if one of [latestActiveSoFar, cur] is active and the other isn't, // if one of [latestActiveSoFar, cur] is active and the other isn't,
// return whichever is active. If both are not active, return // return whichever is active. If both are not active, return
// latestActiveSoFar. // latestActiveSoFar.
@ -62,24 +62,24 @@ module.exports = function (apiKey, serviceId) {
if (!this.serviceId) { if (!this.serviceId) {
return cb('Failed to set condition. No serviceId configured'); return cb('Failed to set condition. No serviceId configured');
} }
var name = condition.name; const name = condition.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition/' + encodeURIComponent(name); const putUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/condition/${encodeURIComponent(name)}`;
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/condition'; const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/condition`;
return this.request('PUT', putUrl, condition, function (err, response) { return this.request('PUT', putUrl, condition, (err, response) => {
if (err && err.statusCode === 404) { if (err && err.statusCode === 404) {
this.request('POST', postUrl, condition, function (e, resp) { this.request('POST', postUrl, condition, (e, resp) => {
if (e) { if (e) {
return cb('Failed while inserting condition "' + condition.statement + '": ' + e); return cb(`Failed while inserting condition "${condition.statement}": ${e}`);
} }
return cb(null, resp); return cb(null, resp);
}); });
return; return;
} }
if (err) { if (err) {
return cb('Failed to update condition "' + condition.statement + '": ' + err); return cb(`Failed to update condition "${condition.statement}": ${err}`);
} }
return cb(null, response); return cb(null, response);
}.bind(this)); });
}; };
/* /*
@ -94,24 +94,24 @@ module.exports = function (apiKey, serviceId) {
if (!this.serviceId) { if (!this.serviceId) {
cb('Failed to set header. No serviceId configured'); cb('Failed to set header. No serviceId configured');
} }
var name = header.name; const name = header.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header/' + encodeURIComponent(name); const putUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/header/${encodeURIComponent(name)}`;
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/header'; const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/header`;
return this.request('PUT', putUrl, header, function (err, response) { return this.request('PUT', putUrl, header, (err, response) => {
if (err && err.statusCode === 404) { if (err && err.statusCode === 404) {
this.request('POST', postUrl, header, function (e, resp) { this.request('POST', postUrl, header, (e, resp) => {
if (e) { if (e) {
return cb('Failed to insert header: ' + e); return cb(`Failed to insert header: ${e}`);
} }
return cb(null, resp); return cb(null, resp);
}); });
return; return;
} }
if (err) { if (err) {
return cb('Failed to update header: ' + err); return cb(`Failed to update header: ${err}`);
} }
return cb(null, response); return cb(null, response);
}.bind(this)); });
}; };
/* /*
@ -126,24 +126,25 @@ module.exports = function (apiKey, serviceId) {
if (!this.serviceId) { if (!this.serviceId) {
cb('Failed to set response object. No serviceId configured'); cb('Failed to set response object. No serviceId configured');
} }
var name = responseObj.name; const name = responseObj.name;
var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object/' + encodeURIComponent(name); const putUrl =
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object'; `${this.getFastlyAPIPrefix(this.serviceId, version)}/response_object/${encodeURIComponent(name)}`;
return this.request('PUT', putUrl, responseObj, function (err, response) { const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/response_object`;
return this.request('PUT', putUrl, responseObj, (err, response) => {
if (err && err.statusCode === 404) { if (err && err.statusCode === 404) {
this.request('POST', postUrl, responseObj, function (e, resp) { this.request('POST', postUrl, responseObj, (e, resp) => {
if (e) { if (e) {
return cb('Failed to insert response object: ' + e); return cb(`Failed to insert response object: ${e}`);
} }
return cb(null, resp); return cb(null, resp);
}); });
return; return;
} }
if (err) { if (err) {
return cb('Failed to update response object: ' + err); return cb(`Failed to update response object: ${err}`);
} }
return cb(null, response); return cb(null, response);
}.bind(this)); });
}; };
/* /*
@ -154,7 +155,7 @@ module.exports = function (apiKey, serviceId) {
*/ */
fastly.cloneVersion = function (version, cb) { fastly.cloneVersion = function (version, cb) {
if (!this.serviceId) return cb('Failed to clone version. No serviceId configured.'); if (!this.serviceId) return cb('Failed to clone version. No serviceId configured.');
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/clone'; const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/clone`;
this.request('PUT', url, cb); this.request('PUT', url, cb);
}; };
@ -166,7 +167,7 @@ module.exports = function (apiKey, serviceId) {
*/ */
fastly.activateVersion = function (version, cb) { fastly.activateVersion = function (version, cb) {
if (!this.serviceId) return cb('Failed to activate version. No serviceId configured.'); if (!this.serviceId) return cb('Failed to activate version. No serviceId configured.');
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/activate'; const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/activate`;
this.request('PUT', url, cb); this.request('PUT', url, cb);
}; };
@ -184,25 +185,25 @@ module.exports = function (apiKey, serviceId) {
return cb('Failed to set response object. No serviceId configured'); return cb('Failed to set response object. No serviceId configured');
} }
var url = this.getFastlyAPIPrefix(this.serviceId, version) + '/vcl/' + name; const url = `${this.getFastlyAPIPrefix(this.serviceId, version)}/vcl/${name}`;
var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/vcl'; const postUrl = `${this.getFastlyAPIPrefix(this.serviceId, version)}/vcl`;
var content = {content: vcl}; const content = {content: vcl};
return this.request('PUT', url, content, function (err, response) { return this.request('PUT', url, content, (err, response) => {
if (err && err.statusCode === 404) { if (err && err.statusCode === 404) {
content.name = name; content.name = name;
this.request('POST', postUrl, content, function (e, resp) { this.request('POST', postUrl, content, (e, resp) => {
if (e) { if (e) {
return cb('Failed while adding custom vcl "' + name + '": ' + e); return cb(`Failed while adding custom vcl "${name}": ${e}`);
} }
return cb(null, resp); return cb(null, resp);
}); });
return; return;
} }
if (err) { if (err) {
return cb('Failed to update custom vcl "' + name + '": ' + err); return cb(`Failed to update custom vcl "${name}": ${err}`);
} }
return cb(null, response); return cb(null, response);
}.bind(this)); });
}; };
return fastly; return fastly;

View file

@ -9,7 +9,7 @@ const Handler = function (route) {
}; };
} }
var url = '/' + route.name + '.html'; const url = `/${route.name}.html`;
return function (req, res, next) { return function (req, res, next) {
req.url = url; req.url = url;
next(); next();

View file

@ -1,16 +1,16 @@
var express = require('express'); const express = require('express');
var proxy = require('express-http-proxy'); const proxy = require('express-http-proxy');
var webpackDevMiddleware = require('webpack-dev-middleware'); const webpackDevMiddleware = require('webpack-dev-middleware');
var webpack = require('webpack'); const webpack = require('webpack');
var compiler = webpack(require('../webpack.config.js')); const compiler = webpack(require('../webpack.config.js'));
var handler = require('./handler'); const handler = require('./handler');
var log = require('./log'); const log = require('./log');
var routes = require('../src/routes.json').concat(require('../src/routes-dev.json')) const routes = require('../src/routes.json').concat(require('../src/routes-dev.json'))
.filter(route => !process.env.VIEW || process.env.VIEW === route.view); .filter(route => !process.env.VIEW || process.env.VIEW === route.view);
// Create server // Create server
var app = express(); const app = express();
app.disable('x-powered-by'); app.disable('x-powered-by');
// Server setup // Server setup
@ -21,11 +21,11 @@ routes.forEach(route => {
app.get(route.pattern, handler(route)); app.get(route.pattern, handler(route));
}); });
var middlewareOptions = {}; const middlewareOptions = {};
app.use(webpackDevMiddleware(compiler, middlewareOptions)); app.use(webpackDevMiddleware(compiler, middlewareOptions));
var proxyHost = process.env.FALLBACK || ''; const proxyHost = process.env.FALLBACK || '';
if (proxyHost !== '') { if (proxyHost !== '') {
// Fall back to scratchr2 in development // Fall back to scratchr2 in development
// This proxy middleware must come last // This proxy middleware must come last
@ -33,10 +33,10 @@ if (proxyHost !== '') {
} }
// Start listening // Start listening
var port = process.env.PORT || 8333; const port = process.env.PORT || 8333;
app.listen(port, function () { app.listen(port, () => {
process.stdout.write('Server listening on port ' + port + '\n'); process.stdout.write(`Server listening on port ${port}\n`);
if (proxyHost) { if (proxyHost) {
process.stdout.write('Proxy host: ' + proxyHost + '\n'); process.stdout.write(`Proxy host: ${proxyHost}\n`);
} }
}); });

View file

@ -1,7 +1,7 @@
var bunyan = require('bunyan'); const bunyan = require('bunyan');
module.exports = function () { module.exports = function () {
var logger = bunyan.createLogger({ const logger = bunyan.createLogger({
name: 'www', name: 'www',
serializers: {req: bunyan.stdSerializers.req} serializers: {req: bunyan.stdSerializers.req}
}); });

View file

@ -13,8 +13,9 @@ const TerserPlugin = require('terser-webpack-plugin');
// PostCss // PostCss
const autoprefixer = require('autoprefixer'); const autoprefixer = require('autoprefixer');
/** @type {Array} */
let routes = require('./src/routes.json'); let routes = require('./src/routes.json');
const templateConfig = require('./src/template-config.js'); // eslint-disable-line global-require const templateConfig = require('./src/template-config.js');
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
routes = routes.concat(require('./src/routes-dev.json')); // eslint-disable-line global-require routes = routes.concat(require('./src/routes-dev.json')); // eslint-disable-line global-require
@ -22,10 +23,8 @@ if (process.env.NODE_ENV !== 'production') {
routes = routes.filter(route => !process.env.VIEW || process.env.VIEW === route.view); routes = routes.filter(route => !process.env.VIEW || process.env.VIEW === route.view);
const pageRoutes = routes.filter(function (route) { const pageRoutes = routes.filter(route => !route.redirect);
return !route.redirect; const VersionPlugin = function (options) {
});
let VersionPlugin = function (options) {
this.options = options || {}; this.options = options || {};
return this; return this;
}; };
@ -44,10 +43,10 @@ VersionPlugin.prototype.apply = function (compiler) {
}; };
const options = this.options; const options = this.options;
compiler.plugin('emit', function (compilation, callback) { compiler.plugin('emit', (compilation, callback) => {
const sha = process.env.WWW_VERSION; const sha = process.env.WWW_VERSION;
if (!sha) { // eslint-disable-line no-negated-condition if (!sha) { // eslint-disable-line no-negated-condition
gitsha(options, function (err, _sha) { gitsha(options, (err, _sha) => {
if (err) return callback(err); if (err) return callback(err);
return addVersion(compilation, _sha, callback); return addVersion(compilation, _sha, callback);
}); });
@ -58,9 +57,9 @@ VersionPlugin.prototype.apply = function (compiler) {
}; };
// Prepare all entry points // Prepare all entry points
let entry = {}; const entry = {};
pageRoutes.forEach(function (route) { pageRoutes.forEach(route => {
entry[route.name] = [ entry[route.name] = [
'./src/init.js', './src/init.js',
`./src/views/${route.view}.jsx` `./src/views/${route.view}.jsx`
@ -167,14 +166,12 @@ module.exports = {
new MiniCssExtractPlugin(), new MiniCssExtractPlugin(),
new VersionPlugin({length: 5}) new VersionPlugin({length: 5})
].concat(pageRoutes ].concat(pageRoutes
.map(function (route) { .map(route => new HtmlWebpackPlugin(defaults({}, {
return new HtmlWebpackPlugin(defaults({}, { title: route.title,
title: route.title, filename: `${route.name}.html`,
filename: route.name + '.html', route: route,
route: route, dynamicMetaTags: route.dynamicMetaTags
dynamicMetaTags: route.dynamicMetaTags }, templateConfig)))
}, templateConfig));
})
).concat([ ).concat([
new CopyWebpackPlugin({ new CopyWebpackPlugin({
patterns: [ patterns: [
@ -206,16 +203,16 @@ module.exports = {
] ]
}), }),
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env.NODE_ENV': '"' + (process.env.NODE_ENV || 'development') + '"', 'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"`,
'process.env.API_HOST': '"' + (process.env.API_HOST || 'https://api.scratch.mit.edu') + '"', 'process.env.API_HOST': `"${process.env.API_HOST || 'https://api.scratch.mit.edu'}"`,
'process.env.RECAPTCHA_SITE_KEY': '"' + 'process.env.RECAPTCHA_SITE_KEY': `"${
(process.env.RECAPTCHA_SITE_KEY || '6Lf6kK4UAAAAABKTyvdSqgcSVASEnMrCquiAkjVW') + '"', process.env.RECAPTCHA_SITE_KEY || '6Lf6kK4UAAAAABKTyvdSqgcSVASEnMrCquiAkjVW'}"`,
'process.env.ASSET_HOST': '"' + (process.env.ASSET_HOST || 'https://assets.scratch.mit.edu') + '"', 'process.env.ASSET_HOST': `"${process.env.ASSET_HOST || 'https://assets.scratch.mit.edu'}"`,
'process.env.BACKPACK_HOST': '"' + (process.env.BACKPACK_HOST || 'https://backpack.scratch.mit.edu') + '"', 'process.env.BACKPACK_HOST': `"${process.env.BACKPACK_HOST || 'https://backpack.scratch.mit.edu'}"`,
'process.env.CLOUDDATA_HOST': '"' + (process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu') + '"', 'process.env.CLOUDDATA_HOST': `"${process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu'}"`,
'process.env.PROJECT_HOST': '"' + (process.env.PROJECT_HOST || 'https://projects.scratch.mit.edu') + '"', 'process.env.PROJECT_HOST': `"${process.env.PROJECT_HOST || 'https://projects.scratch.mit.edu'}"`,
'process.env.STATIC_HOST': '"' + (process.env.STATIC_HOST || 'https://uploads.scratch.mit.edu') + '"', 'process.env.STATIC_HOST': `"${process.env.STATIC_HOST || 'https://uploads.scratch.mit.edu'}"`,
'process.env.SCRATCH_ENV': '"' + (process.env.SCRATCH_ENV || 'development') + '"' 'process.env.SCRATCH_ENV': `"${process.env.SCRATCH_ENV || 'development'}"`
}) })
]) ])
.concat(process.env.ANALYZE_BUNDLE === 'true' ? [ .concat(process.env.ANALYZE_BUNDLE === 'true' ? [