Files
Taekwondo-Admin/packages/api/src/index.ts
T
2026-03-16 00:46:30 +01:00

160 lines
4.7 KiB
TypeScript

import constants from "constants";
import cors from "cors";
import { CronJob } from "cron";
import express, {
type NextFunction,
type Request,
type Response,
} from "express";
import fs from "fs";
import https from "https";
import { RegisterRoutes } from "./generated/routes.js";
import { inject } from "./infrastructure/di/injector.js";
import { sessionHandler } from "./infrastructure/sessionHandler.js";
import { EnvironmentService } from "./services/environmentService.js";
import { FoundEventsService } from "./services/foundEvents/foundEventsService.js";
import { KeycloakUser } from "./services/keycloak/user/keycloak-user.js";
import { PushService } from "./services/push/pushService.js";
// import helmet from "helmet";
// TODO import http2 from 'http2';
async function run() {
const app = express();
const keycloakUser = inject(KeycloakUser);
//TODO app.use(helmet.hsts()); this and other helmets
app.use(
cors({
origin: [
"https://taekwondo-chemnitz.toni714.de",
"https://tcc-1-ev-intern.web.app",
"http://localhost:4200",
"https://localhost:4200",
"http://localhost:8080",
],
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
//TODO reevaluate
}),
);
app.use(sessionHandler);
app.use(await keycloakUser.middleware());
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
RegisterRoutes(app);
const environment = inject(EnvironmentService);
// wants to be last
app.use(
(err: unknown, _req: Request, res: Response, _next: NextFunction) => {
console.dir(err);
const ex = JSON.stringify(err);
res.header("Content-Length", `${ex.length}`);
res.status(500).send(ex);
throw err;
},
);
const isDev = environment.isDev();
let cert: https.ServerOptions["cert"];
let key: https.ServerOptions["key"];
let SSL_KEY_PASSWORD: string | undefined;
let port: number;
if (isDev) {
//TODO start with HTTPS in dev
// cert = fs.readFileSync("src/cert.pem");
// key = fs.readFileSync("src/key.pem");
port = 3000;
const server = app.listen(port, error => {
if (error) {
console.error("Startup crashed:", error);
}
console.log(`Server is running at http://localhost:${port}`);
});
server.on("close", () => stopCron());
} else {
port = 5443;
const SSL_CERT_PATH = process.env["SSL_CERT_PATH"];
const SSL_KEY_PATH = process.env["SSL_KEY_PATH"];
SSL_KEY_PASSWORD = process.env["SSL_KEY_PASSWORD"];
if (!SSL_CERT_PATH || !SSL_KEY_PATH || !SSL_KEY_PASSWORD) {
throw new Error("Missing SSL configuration");
}
cert = fs.readFileSync(SSL_CERT_PATH);
key = fs.readFileSync(SSL_KEY_PATH);
const sslOptions: https.ServerOptions = {
cert: cert,
key: key,
passphrase: SSL_KEY_PASSWORD,
minVersion: "TLSv1.3",
maxVersion: "TLSv1.3",
ecdhCurve: "X25519:prime256v1:secp384r1",
honorCipherOrder: false,
secureOptions:
constants.SSL_OP_NO_TLSv1 |
constants.SSL_OP_NO_TLSv1_1 |
constants.SSL_OP_NO_TLSv1_2 |
constants.SSL_OP_NO_SSLv2 |
constants.SSL_OP_NO_SSLv3,
};
const server = https.createServer(sslOptions, app).listen(port, () => {
console.log(`Server is running on port ${port}`);
});
server.on("close", () => stopCron());
}
// const h2SslOptions={};
// http2.createServer(h2SslOptions, app).listen(port, ()=>{
// console.log(`HTTP/2 server is running on port ${port}`);
// })
initJobs();
startCron();
console.log("setup done");
}
const jobs: CronJob[] = [];
function initJobs() {
const eventsService = inject(FoundEventsService);
const crawlJob = CronJob.from({
cronTime: "35 4 * * *",
onTick: async () => {
await eventsService.crawl();
},
});
jobs.push(crawlJob);
const pushService = inject(PushService);
const notifyJob = CronJob.from({
cronTime: "10 12 * * *",
onTick: async () => {
await pushService.sendEventNotifications();
},
});
jobs.push(notifyJob);
}
function startCron() {
console.log("starting jobs");
for (const job of jobs) {
job.start();
}
}
async function stopCron() {
console.log("stopping jobs");
for (const job of jobs) {
job.stop();
}
}
run();