Files
talk/middleware/staticTemplate.js
T
2018-05-07 14:27:00 -06:00

117 lines
2.9 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)
);
}
/**
* resolveFactory is a function that can be used in templates to resolve an
* asset from the manifest. In production, the manifest is cached.
*/
const createResolveFactory = (() => {
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 () => {
let manifest = {};
try {
manifest = getManifest();
} catch (err) {
console.warn(err);
}
return key =>
key in manifest ? `${STATIC_URL}static/${manifest[key]}` : '';
};
})();
module.exports = async (req, res, next) => {
try {
// Attach the custom css url.
const { customCssUrl } = await SettingsService.select('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 = createResolveFactory();
// Forward the request.
next();
};
module.exports.attachStaticLocals = attachStaticLocals;
module.exports.TEMPLATE_LOCALS = TEMPLATE_LOCALS;