import {Router} from 'express'; import {DefaultConfig, Logger, urlJoin} from '.'; import {v4} from 'uuid'; import Timeout = NodeJS.Timeout; export type ReloaderConfig = { // frontend directories to watch frontendDirs: string|string[], // auto reloader sub path (defaults to '/auto-reload') subPath?: string, // auto reloader js name (defaults to 'client.js') jsName?: string, } type IntReloaderConfig = { // frontend directories to watch frontendDirs: string[], // auto reloader sub path (defaults to '/auto-reload') subPath: string, // auto reloader js name (defaults to 'client.js') jsName: string, } function getRouter(opts: ReloaderConfig): Router { const config: IntReloaderConfig = { frontendDirs: Array.isArray(opts.frontendDirs) ? opts.frontendDirs : [opts.frontendDirs], subPath: opts.subPath || '/auto-reload', jsName: opts.jsName || 'client.js', }; const router = Router(); if (!DefaultConfig.isProduction) { let uuid = v4(); let updateTimeout: Timeout|undefined = undefined; import('node-watch').then((watch) => { for (const frontendDir of config.frontendDirs) { watch.default(frontendDir, {recursive: true}, () => { if (updateTimeout !== undefined) clearTimeout(updateTimeout); updateTimeout = setTimeout(() => { uuid = v4(); }, 200); }); } }).catch((err) => { Logger.error(err); }); // /auto-reload/client.js router.get(urlJoin(config.subPath, config.jsName), (req, res) => { Logger.debug(req.url, req.originalUrl, req.baseUrl); res.setHeader('Content-Type', 'application/javascript'); // language=JavaScript res.send(` const loc = window.location; const url = loc.protocol+'//'+loc.host+'${urlJoin(req.baseUrl, config.subPath)}'; // const parse = async res => (await res.json()).uuid; const parse = function(res) { return res.json() .then(function(json) {return json.uuid;}) } let hash = undefined; let hadError = false; setInterval(function() { try { fetch(url) .then(function(res) { return parse(res) }) .then(function(data) { if (data) { hash = hash === undefined ? data : hash; if (hash !== data) { window.location.reload(); } } }); } catch (e) { if (hadError === false) { console.log(e); hadError = true; } } }, 3000); `.replace(/\t/g, '')); }); // /auto-reload router.get(urlJoin(config.subPath), (req, res) => { req.noHttpLogging = true; res.json({uuid}); }); } return router; } export const AutoReloader = { getRouter, };