Files
Termix/src/backend/starter.ts

145 lines
4.1 KiB
TypeScript

import dotenv from "dotenv";
import { promises as fs } from "fs";
import { readFileSync } from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { AutoSSLSetup } from "./utils/auto-ssl-setup.js";
import { AuthManager } from "./utils/auth-manager.js";
import { DataCrypto } from "./utils/data-crypto.js";
import { SystemCrypto } from "./utils/system-crypto.js";
import { systemLogger, versionLogger } from "./utils/logger.js";
(async () => {
try {
dotenv.config({ quiet: true });
const dataDir = process.env.DATA_DIR || "./db/data";
const envPath = path.join(dataDir, ".env");
try {
await fs.access(envPath);
const persistentConfig = dotenv.config({ path: envPath, quiet: true });
if (persistentConfig.parsed) {
Object.assign(process.env, persistentConfig.parsed);
}
} catch (error) {}
let version = "unknown";
const versionSources = [
() => process.env.VERSION,
() => {
try {
const packageJsonPath = path.join(process.cwd(), "package.json");
const packageJson = JSON.parse(
readFileSync(packageJsonPath, "utf-8"),
);
return packageJson.version;
} catch {
return null;
}
},
() => {
try {
const __filename = fileURLToPath(import.meta.url);
const packageJsonPath = path.join(
path.dirname(__filename),
"../../../package.json",
);
const packageJson = JSON.parse(
readFileSync(packageJsonPath, "utf-8"),
);
return packageJson.version;
} catch {
return null;
}
},
() => {
try {
const packageJsonPath = path.join("/app", "package.json");
const packageJson = JSON.parse(
readFileSync(packageJsonPath, "utf-8"),
);
return packageJson.version;
} catch {
return null;
}
},
];
for (const getVersion of versionSources) {
try {
const foundVersion = getVersion();
if (foundVersion && foundVersion !== "unknown") {
version = foundVersion;
break;
}
} catch {
continue;
}
}
versionLogger.info(`Termix Backend starting - Version: ${version}`, {
operation: "startup",
version: version,
});
const systemCrypto = SystemCrypto.getInstance();
await systemCrypto.initializeJWTSecret();
await systemCrypto.initializeDatabaseKey();
await systemCrypto.initializeInternalAuthToken();
await AutoSSLSetup.initialize();
const dbModule = await import("./database/db/index.js");
await dbModule.initializeDatabase();
const authManager = AuthManager.getInstance();
await authManager.initialize();
DataCrypto.initialize();
await import("./database/database.js");
await import("./ssh/terminal.js");
await import("./ssh/tunnel.js");
await import("./ssh/file-manager.js");
await import("./ssh/server-stats.js");
await import("./ssh/docker.js");
await import("./ssh/docker-console.js");
await import("./dashboard.js");
process.on("SIGINT", () => {
systemLogger.info(
"Received SIGINT signal, initiating graceful shutdown...",
{ operation: "shutdown" },
);
process.exit(0);
});
process.on("SIGTERM", () => {
systemLogger.info(
"Received SIGTERM signal, initiating graceful shutdown...",
{ operation: "shutdown" },
);
process.exit(0);
});
process.on("uncaughtException", (error) => {
systemLogger.error("Uncaught exception occurred", error, {
operation: "error_handling",
});
process.exit(1);
});
process.on("unhandledRejection", (reason) => {
systemLogger.error("Unhandled promise rejection", reason, {
operation: "error_handling",
});
process.exit(1);
});
} catch (error) {
systemLogger.error("Failed to initialize backend services", error, {
operation: "startup_failed",
});
process.exit(1);
}
})();