import {Express, Router} from "express"; import path from "path"; import config from "config"; import ApplicationComponent from "../ApplicationComponent"; import {logger} from "../Logger"; import "svelte/register"; import ViewEngine from "../frontend/ViewEngine"; import {readdirRecursively} from "../Utils"; import FileCache from "../utils/FileCache"; export default class FrontendToolsComponent extends ApplicationComponent { private readonly publicAssetsCache: FileCache = new FileCache(); public constructor( private readonly viewEngine: ViewEngine, ) { super(); } public async start(app: Express): Promise { // Cache public assets if (config.get('view.enable_asset_cache')) { logger.info('Caching assets from', this.viewEngine.getPublicDir(), '...'); await readdirRecursively( this.viewEngine.getPublicDir(), async file => await this.publicAssetsCache.load(file), ); } else { logger.info('Asset cache disabled.'); } // Pre-compile and watch in dev mode if (config.get('view.dev')) { await this.viewEngine.preCompileAll(); await this.viewEngine.watch(); } // Setup express view engine app.engine(this.viewEngine.getExtension(), (path, options, callback) => { this.viewEngine.render(path, options as Record, callback) .catch(err => callback(err)); }); app.set('views', this.viewEngine.getViewPaths()); app.set('view engine', 'svelte'); } public async stop(): Promise { await this.viewEngine.end?.(); } public async handle(router: Router): Promise { router.use((req, res, next) => { res.locals.inlineAsset = (urlPath: string) => { return this.publicAssetsCache.getOrFail(path.join(this.viewEngine.getPublicDir(), urlPath)); }; next(); }); } }