import express, { Express } from "express"; import { ServerMessages } from "../route/messages"; import { Route } from "../route/route"; type ServerConfig = { port: number; routes?: Route[]; }; export default class Server { /** * The port that this server is listening on. */ private port: number; /** * The express server. */ private server: Express; /** * The routes that this server is serving. */ private routes: Route[] = []; constructor({ port, routes }: ServerConfig) { this.port = port; if (routes) { this.routes.push(...routes); } // Create the express server this.server = express(); this.preInit(); // Setup route logging this.server.use((req, res, next) => { // TODO: make this look better? console.log(`[${req.method}] ${req.path}`); next(); }); // Handle the routes for (const route of this.routes) { this.server.all(route.getPath(), (req, res, next) => { if (req.method.toUpperCase() !== route.getMethod().toUpperCase()) { return next(); // Skip this method } try { route.handle(req, res, next); } catch (ex) { console.error(ex); // Inform the user that an internal server error occurred res.status(500).json(ServerMessages.internalServerError()); } }); } // Log the registered routes console.log(`Registered ${this.routes.length} routes`); for (const route of this.routes) { console.log(` - ${route.getMethod().toUpperCase()} ${route.getPath()}`); } // Handle unknown routes this.server.all("*", (req, res) => { res.status(404).send("404 Not Found"); }); // Start listening on the specified port this.server.listen(this.port, () => { console.log(`Server listening on http://localhost:${this.port}`); this.postInit(); }); } /** * Returns the port that this server is listening on. * * @returns {number} the port */ public getPort() { return this.port; } /** * Registers a list of routes. * * @param route the routes to register */ public registerRoute(...routes: Route[]) { this.routes.push(...routes); } public getRoute(path: string): Route | undefined { return this.routes.find((route) => route.getPath() === path); } /** * Gets called before the server starts listening. */ public preInit(): void {} /** * Gets called after the server starts listening. */ public postInit(): void {} }