UNPKG

@axway/api-builder-runtime

Version:

API Builder Runtime

114 lines (106 loc) 3.35 kB
const fs = require('fs'); const path = require('path'); const express = require('express'); class RenderEngineManager { constructor(app, { appDir, logger }) { this._app = app; this._logger = logger; this._renderers = {}; this._cache = {}; if (appDir) { this._webDirectory = path.join(appDir, 'web'); this._viewsDirectory = path.join(this._webDirectory, 'views'); this._routesDirectory = path.join(this._webDirectory, 'routes'); this._publicDirectory = path.join(this._webDirectory, 'public'); } } /** * Enables the static `./public` directory on the express app. This is an * internal method to be used by unit-tests only. * @private */ registerPublicStatic() { const logger = this._logger; if (this._publicDirectory && fs.existsSync(this._publicDirectory)) { logger.debug('serve public files:', this._publicDirectory); this._app.use(express.static(this._publicDirectory)); } } registerRenderers() { const logger = this._logger; if (!this._viewsDirectory || !fs.existsSync(this._viewsDirectory)) { logger.debug('No views directory, disabling'); } else { this._app.set('views', this._viewsDirectory); } const dir = path.join(__dirname, '..', 'engines'); const engines = fs.readdirSync(dir); for (const engineType of engines) { const engine = require(path.join(dir, engineType)); logger.trace('Registering render engine:', engineType); if (engine.createRenderer) { this.registerRendererEngine(engine); } } // we monkey patch express to make it easy to switch between different // templating engines without forcing us to register a default one const originalRender = this._app.render; this._app.render = (view, data, callback) => { let ext = path.extname(view); if (!ext || ext === view) { // no extension, search for it const keys = Object.keys(this._renderers); let found = false; for (let c = 0; c < keys.length; c++) { ext = keys[c]; const fn = path.join(this._viewsDirectory, `${view}.${ext}`); // we found a template for a specific engine, append the // extension to trick express into using this specific // engine if (fs.existsSync(fn)) { view += '.' + ext; found = true; break; } } if (!found) { return callback(new Error(`Unable to find layout "${view}"`)); } } return originalRender.call(this._app, view, data, callback); }; } registerRendererEngine(engine) { this._createRenderer(engine); this._renderers[engine.extension] = engine; } getRendererEngine(extension) { // in case they supplied a . return this._renderers[extension] || this._renderers[extension.substring(1)]; } _createRenderer(engine) { const { extension: ext } = engine; const cacheable = this._app.enabled('view cache'); this._app.engine(ext, (filePath, options, callback) => { let entry = this._cache[filePath]; if (!entry || !cacheable) { const file = engine.skipread ? null : fs.readFileSync(filePath).toString(); entry = engine.createRenderer(file, filePath, this._app); if (cacheable) { this._cache[filePath] = entry; } } if (entry.length === 3) { entry(filePath, options, callback); } else { callback(null, entry(options)); } }); } } module.exports = { RenderEngineManager };