1import express from 'express';
2import path from 'node:path';
3import fs from 'node:fs';
4import https from 'node:https';
5import * as timerTask from './tasks/timer.js';
6import * as integrationTask from './tasks/integrations.js';
7import './util/createFolders.js';
8import './util/loadServers.js';
9import errorHandler from './util/errorHandler.js';
10import errorMiddleware from './middlewares/error.js';
11import configRoutes from './routes/config.js';
12import speedtestsRoutes from './routes/speedtests.js';
13import systemRoutes from './routes/system.js';
14import storageRoutes from './routes/storage.js';
15import recommendationsRoutes from './routes/recommendations.js';
16import nodesRoutes from './routes/nodes.js';
17import integrationsRoutes from './routes/integrations.js';
18import prometheusRoutes from './routes/prometheus.js';
19import opengraphRoutes from './routes/opengraph.js';
20import db from './config/database.js';
21import { runMigrations } from './util/migrationRunner.js';
22import * as config from './controller/config.js';
23import { initialize as initializeIntegrations } from './controller/integrations.js';
24import { requestInterfaces } from './util/loadInterfaces.js';
25import { load as loadCli } from './util/loadCli.js';
26import { removeOld } from './tasks/speedtest.js';
27
28const devModeHtmlPath = path.join(process.cwd(), 'server', 'templates', 'env.html');
29const devModeHtml = fs.existsSync(devModeHtmlPath) ? fs.readFileSync(devModeHtmlPath, 'utf-8') : '';
30
31let embeddedClient = null;
32try {
33 embeddedClient = await import('./clientEmbed.js');
34} catch {
35
36}
37
38const app = express();
39
40app.disable('x-powered-by');
41
42const port = process.env.SERVER_PORT || 5216;
43const httpsPort = process.env.HTTPS_PORT || 5217;
44
45const certsDir = path.join(process.cwd(), 'data', 'certs');
46const certPath = path.join(certsDir, 'cert.pem');
47const keyPath = path.join(certsDir, 'key.pem');
48
49const hasSSLCerts = () => fs.existsSync(certPath) && fs.existsSync(keyPath);
50
51process.on('uncaughtException', err => errorHandler(err));
52
53app.use(express.json({ limit: '50mb' }));
54app.use(errorMiddleware);
55
56app.use("/api/config", configRoutes);
57app.use("/api/speedtests", speedtestsRoutes);
58app.use("/api/info", systemRoutes);
59app.use("/api/storage", storageRoutes);
60app.use("/api/recommendations", recommendationsRoutes);
61app.use("/api/nodes", nodesRoutes);
62app.use("/api/integrations", integrationsRoutes);
63app.use("/api/prometheus", prometheusRoutes);
64app.use('/api/opengraph', opengraphRoutes);
65app.use("/api*all", (req, res) => res.status(404).json({message: "Route not found"}));
66
67let buildPath = path.join(process.cwd(), 'build');
68let buildExists = fs.existsSync(buildPath);
69
70if (buildExists) {
71 app.use(express.static(buildPath));
72 app.get('*all', (req, res) => res.sendFile(path.join(buildPath, 'index.html')));
73} else if (embeddedClient) {
74 app.use(embeddedClient.createEmbeddedMiddleware());
75 app.get('*all', embeddedClient.createEmbeddedFallback());
76} else {
77 app.get("*all", (req, res) => res.status(500).type('html').send(devModeHtml));
78}
79
80const run = async () => {
81 await runMigrations();
82
83 await initializeIntegrations();
84
85 await requestInterfaces();
86 setInterval(() => requestInterfaces(), 3600000);
87
88 if (process.env.PREVIEW_MODE !== "true") await loadCli();
89
90 await config.insertDefaults();
91
92 timerTask.startTimer(await config.getValue("cron"));
93 setInterval(async () => removeOld(), 60000);
94
95 integrationTask.startTimer();
96 if (process.env.RUN_TEST_ON_STARTUP === "true") {
97 timerTask.runTask().then(undefined);
98 }
99
100 app.listen(port, () => console.log(`Server listening on port ${port}`));
101
102 if (hasSSLCerts()) {
103 try {
104 const sslOptions = {
105 cert: fs.readFileSync(certPath),
106 key: fs.readFileSync(keyPath)
107 };
108
109 https.createServer(sslOptions, app).listen(httpsPort, () =>
110 console.log(`HTTPS server listening on port ${httpsPort}`)
111 );
112 } catch (err) {
113 console.error(`Failed to start HTTPS server: ${err.message}`);
114 }
115 }
116}
117
118db.authenticate().then(() => {
119 console.log("Successfully connected to the database " + (process.env.DB_TYPE === "mysql" ? "server" : "file"));
120 run().then(undefined);
121}).catch(err => {
122 console.error("Could not open the database file. Maybe it is damaged?: " + err.message);
123 process.exit(111);
124});