swaf/src/components/FrontendToolsComponent.ts

103 lines
3.3 KiB
TypeScript
Raw Normal View History

import "../../node_modules/svelte/register.js";
import config from "config";
2021-03-24 16:07:50 +01:00
import {Express, Router} from "express";
2021-03-18 16:22:25 +01:00
import path from "path";
import * as querystring from "querystring";
import {ParsedUrlQueryInput} from "querystring";
import util from "util";
2021-03-18 16:22:25 +01:00
import ApplicationComponent from "../ApplicationComponent.js";
import Controller, {RouteParams} from "../Controller.js";
import ViewEngine from "../frontend/ViewEngine.js";
import {logger} from "../Logger.js";
import {readdirRecursively} from "../Utils.js";
import FileCache from "../utils/FileCache.js";
2021-03-18 16:22:25 +01:00
export default class FrontendToolsComponent extends ApplicationComponent {
2021-03-24 21:41:13 +01:00
private readonly publicAssetsCache: FileCache = new FileCache();
private readonly viewEngines: ViewEngine[];
2021-03-18 16:22:25 +01:00
public constructor(
private readonly publicAssetsDir: string,
...viewEngines: ViewEngine[]
2021-03-18 16:22:25 +01:00
) {
super();
this.viewEngines = viewEngines;
2021-03-18 16:22:25 +01:00
}
2021-03-24 16:07:50 +01:00
public async start(app: Express): Promise<void> {
2021-03-24 21:41:13 +01:00
// Cache public assets
if (config.get<boolean>('asset_cache')) {
logger.info('Caching assets from', this.publicAssetsDir, '...');
2021-03-24 21:41:13 +01:00
await readdirRecursively(
this.publicAssetsDir,
2021-03-24 21:41:13 +01:00
async file => await this.publicAssetsCache.load(file),
);
} else {
logger.info('Asset cache disabled.');
}
2021-03-18 16:22:25 +01:00
2021-03-24 21:41:13 +01:00
// Setup express view engine
let main = true;
for (const viewEngine of this.viewEngines) {
viewEngine.setup(app, main);
main = false;
}
// Add util globals
this.setupGlobals();
2021-03-24 16:07:50 +01:00
}
public async stop(): Promise<void> {
for (const viewEngine of this.viewEngines) {
await viewEngine.stop();
}
2021-03-18 16:22:25 +01:00
}
public async handle(router: Router): Promise<void> {
router.use((req, res, next) => {
res.locals.inlineAsset = (urlPath: string) => {
return this.publicAssetsCache.getOrFail(path.join(this.publicAssetsDir, urlPath));
2021-03-18 16:22:25 +01:00
};
2021-03-24 16:07:50 +01:00
2021-03-24 21:41:13 +01:00
next();
2021-03-18 16:22:25 +01:00
});
// Add request context locals
router.use((req, res, next) => {
res.locals.url = req.url;
res.locals.params = req.params;
res.locals.query = req.query;
res.locals.body = req.body;
next();
});
2021-03-18 16:22:25 +01:00
}
public async preCompileViews(watch: boolean): Promise<void> {
for (const viewEngine of this.viewEngines) {
await viewEngine.preCompileAll(watch);
}
}
public setupGlobals(): void {
ViewEngine.setGlobal('route', (
route: string,
params: RouteParams = [],
query: ParsedUrlQueryInput = {},
absolute: boolean = false,
) => Controller.route(route, params, query, absolute));
ViewEngine.setGlobal('app_version', this.getApp().getVersion());
ViewEngine.setGlobal('core_version', this.getApp().getCoreVersion());
ViewEngine.setGlobal('querystring', querystring);
ViewEngine.setGlobal('app', config.get('app'));
ViewEngine.setGlobal('dump', (val: unknown) => {
return util.inspect(val);
});
ViewEngine.setGlobal('hex', (v: number) => {
return v.toString(16);
});
}
2021-03-18 16:22:25 +01:00
}