138 lines
4.3 KiB
TypeScript
138 lines
4.3 KiB
TypeScript
import type { Request, Response, NextFunction } from 'express';
|
|
import express from 'express';
|
|
import bodyParser from 'body-parser';
|
|
import config from 'config';
|
|
import basePath from '../basepath';
|
|
import cookieParser from 'cookie-parser';
|
|
import http from 'http';
|
|
import expressWs from 'express-ws';
|
|
|
|
process.env.TZ = "Etc/GMT";
|
|
|
|
console.log("Loading ketr.ketran");
|
|
|
|
const app = express();
|
|
const server = http.createServer(app);
|
|
|
|
app.use(cookieParser());
|
|
|
|
expressWs(app, server);
|
|
|
|
require("../console-line"); /* Monkey-patch console.log with line numbers */
|
|
|
|
// Temporary debug routes (dev-only). Mount before static so we can
|
|
// inspect what the server receives for base-prefixed requests.
|
|
try {
|
|
// import the debug router using ESM style; fallback to require at runtime if needed
|
|
// (some dev environments may still emit JS commonjs files)
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const debugRouter = require("../routes/debug").default || require("../routes/debug");
|
|
app.use(basePath, debugRouter);
|
|
} catch (e: any) {
|
|
console.error('Failed to mount debug routes (src):', e && e.stack || e);
|
|
}
|
|
|
|
const frontendPath = (config.get("frontendPath") as string).replace(/\/$/, "") + "/",
|
|
serverConfig = config.get("server") as { port: number };
|
|
|
|
console.log("Hosting server from: " + basePath);
|
|
|
|
// DB handles are initialized by the modules below; we don't need file-scoped vars here.
|
|
|
|
app.use((req: Request, _res: Response, next: NextFunction) => {
|
|
console.log(`${req.method} ${req.url}`);
|
|
next();
|
|
});
|
|
|
|
app.use(bodyParser.json());
|
|
|
|
/* App is behind an nginx proxy which we trust, so use the remote address
|
|
* set in the headers */
|
|
app.set("trust proxy", true);
|
|
|
|
app.set("basePath", basePath);
|
|
// basepath is a simple exported string
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const basepathRouter = require("../routes/basepath").default || require("../routes/basepath");
|
|
app.use(basePath, basepathRouter);
|
|
|
|
/* Handle static files first so excessive logging doesn't occur */
|
|
app.use(basePath, express.static(frontendPath, { index: false }));
|
|
|
|
// index route (may be ESM default export)
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const index = require("../routes/index").default || require("../routes/index");
|
|
|
|
if (config.has("admin")) {
|
|
const admin = config.get("admin");
|
|
app.set("admin", admin);
|
|
}
|
|
|
|
// games router
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const gamesRouter = require("../routes/games").default || require("../routes/games");
|
|
app.use(`${basePath}api/v1/games`, gamesRouter);
|
|
|
|
/* Allow loading of the app w/out being logged in */
|
|
app.use(basePath, index);
|
|
|
|
/* /games loads the default index */
|
|
app.use(basePath + "games", index);
|
|
|
|
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
|
app.use(basePath, index);
|
|
|
|
/**
|
|
* Create HTTP server and listen for new connections
|
|
*/
|
|
app.set("port", serverConfig.port);
|
|
|
|
process.on('SIGINT', () => {
|
|
console.log("Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds");
|
|
setTimeout(() => process.exit(-1), 2000);
|
|
server.close(() => process.exit(1));
|
|
});
|
|
|
|
// database initializers
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
import { initGameDB } from '../routes/games/store';
|
|
|
|
initGameDB().then(function(_db: any) {
|
|
// games DB initialized via store facade
|
|
}).then(function() {
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
return Promise.resolve((require("../db/users") as any).default || require("../db/users")).then(function(_db: any) {
|
|
// users DB initialized
|
|
});
|
|
}).then(function() {
|
|
console.log("DB connected. Opening server.");
|
|
server.listen(serverConfig.port, () => {
|
|
console.log(`http/ws server listening on ${serverConfig.port}`);
|
|
});
|
|
}).catch(function(error: any) {
|
|
console.error(error);
|
|
process.exit(-1);
|
|
});
|
|
|
|
server.on("error", function(error: any) {
|
|
if (error.syscall !== "listen") {
|
|
throw error;
|
|
}
|
|
|
|
// handle specific listen errors with friendly messages
|
|
switch (error.code) {
|
|
case "EACCES":
|
|
console.error(serverConfig.port + " requires elevated privileges");
|
|
process.exit(1);
|
|
break;
|
|
case "EADDRINUSE":
|
|
console.error(serverConfig.port + " is already in use");
|
|
process.exit(1);
|
|
break;
|
|
default:
|
|
throw error;
|
|
}
|
|
});
|
|
|
|
export { app, server };
|