/** * Copyright 2023 Kapeta Inc. * SPDX-License-Identifier: BUSL-1.1 */ import express, { Express, Request, Response } from 'express'; import { getSystemBaseDir, readPageFromDisk } from './page-utils'; import { clusterService } from '../clusterService'; import { createServer, Server } from 'http'; import { StormEventPage } from './events'; import { join } from 'path'; export class UIServer { private readonly systemId: string; private server: Server | undefined; private port: number = 50000; constructor(systemId: string) { this.systemId = systemId; } public isRunning() { return !!this.server; } public getUrl() { return `http://localhost:${this.port}`; } public async start() { const app = express(); app.get('/_reset', (req: Request, res: Response) => { /** * Reset page clears local storage and session storage. If a redirect path is provided, * it will redirect to that path. */ res.send( ` ` ); }); // Make it possible to serve static assets app.use(express.static(join(getSystemBaseDir(this.systemId), 'public'), { fallthrough: true })); app.all('/*', (req: Request, res: Response) => { readPageFromDisk(this.systemId, req.params[0], req.method, res); }); this.port = await clusterService.getNextAvailablePort(this.port); return new Promise((resolve, reject) => { this.server = createServer(app); this.server.on('error', reject); this.server.listen(this.port, () => { console.log(`UI Server started on port ${this.port}`); resolve(); }); }); } public close() { if (this.server) { console.log('UI Server closed on port: %s', this.port); this.server.close(); this.server = undefined; } } resolveUrl(screenData: StormEventPage) { return this.resolveUrlFromPath(screenData.payload.path); } resolveUrlFromPath(path: string) { const resolvedPath = path.startsWith('/') ? path : `/${path}`; return `http://localhost:${this.port}${resolvedPath}`; } }