Files
talk/middleware/staticTemplate.js
T
2018-03-21 11:04:41 -06:00

116 lines
2.8 KiB
JavaScript

const SettingsService = require('../services/settings');
const fs = require('fs');
const path = require('path');
const { merge } = require('lodash');
const {
BASE_URL,
BASE_PATH,
MOUNT_PATH,
STATIC_URL,
STATIC_ORIGIN,
} = require('../url');
const { RECAPTCHA_PUBLIC, WEBSOCKET_LIVE_URI } = require('../config');
// Grab TALK_CLIENT_* environment variables.
const TALK_CLIENT = /^TALK_CLIENT_/i;
// TALK_CLIENT_ENV is all the environment keys that are loaded at runtime.
const TALK_CLIENT_ENV = Object.keys(process.env)
.filter(key => TALK_CLIENT.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC,
LIVE_URI: WEBSOCKET_LIVE_URI,
STATIC_URL,
STATIC_ORIGIN,
}
);
// TEMPLATE_LOCALS stores the static data that is provided as a `text/json` on
// to the client from the template.
const TEMPLATE_LOCALS = {
BASE_URL,
BASE_PATH,
MOUNT_PATH,
STATIC_URL,
TALK_CLIENT_ENV,
data: TALK_CLIENT_ENV,
};
// attachStaticLocals will attach the locals to the response only.
const attachStaticLocals = locals => {
for (const key in TEMPLATE_LOCALS) {
const value = TEMPLATE_LOCALS[key];
locals[key] = value;
}
};
// MANIFESTS are all the manifests accessible by Talk.
const MANIFESTS = ['../dist/manifest.json', '../dist/manifest.embed.json'];
// getManifest will retrieve the manifest files and parse the JSON.
function getManifest() {
return merge(
{},
...MANIFESTS.map(f =>
fs.readFileSync(path.resolve(__dirname, f), 'utf8')
).map(JSON.parse)
);
}
/**
* resolve is a function that can be used in templates to resolve an asset from
* the manifest. In production, the manifest is cached.
*/
const resolve = (() => {
if (process.env.NODE_ENV === 'production') {
// In production, we should attempt to load the manifest early.
const manifest = getManifest();
return key => `${STATIC_URL}static/${manifest[key]}`;
}
// In dev mode, we are more forgiving and we always load the
// newest version of the manifest.
return key => {
try {
const manifest = getManifest();
return `${STATIC_URL}static/${manifest[key]}`;
} catch (err) {
console.warn(err);
return '';
}
};
})();
module.exports = async (req, res, next) => {
try {
// Attach the custom css url.
const { customCssUrl } = await SettingsService.retrieve('customCssUrl');
res.locals.customCssUrl = customCssUrl;
} catch (err) {
console.warn(err);
}
// Always attach the locals.
attachStaticLocals(res.locals);
// Resolve will help resolving paths to static files
// using the manifest.
res.locals.resolve = resolve;
// Forward the request.
next();
};
module.exports.attachStaticLocals = attachStaticLocals;
module.exports.TEMPLATE_LOCALS = TEMPLATE_LOCALS;