81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import { Elysia } from "elysia";
|
|
import { config, validateConfig } from "./config";
|
|
import { runMigrations } from "./db/migrate";
|
|
import { closePool } from "./db/connection";
|
|
import { bugReportRoutes } from "./routes/bugReports";
|
|
import { adminRoutes } from "./routes/admin";
|
|
import { authRoutes } from "./routes/auth";
|
|
import { initLogger, Log } from "./logger";
|
|
|
|
const INSTANCE_ID = process.env.HOSTNAME + "_" + Math.random().toString(16).slice(2, 6);
|
|
|
|
// Initialize logger
|
|
initLogger();
|
|
|
|
// Validate environment
|
|
validateConfig();
|
|
|
|
// Run database migrations
|
|
try {
|
|
await runMigrations();
|
|
} catch (error) {
|
|
Log("ERROR", "Failed to run migrations:", error);
|
|
process.exit(1);
|
|
}
|
|
|
|
const app = new Elysia()
|
|
.onRequest(({ request }) => {
|
|
const url = new URL(request.url);
|
|
const ip =
|
|
request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() ||
|
|
request.headers.get("x-real-ip") ||
|
|
"unknown";
|
|
Log("HTTP", `[${INSTANCE_ID}] ${request.method} ${url.pathname} from ${ip}`);
|
|
})
|
|
.onAfterResponse(({ request, set }) => {
|
|
const url = new URL(request.url);
|
|
Log("HTTP", `${request.method} ${url.pathname} -> ${set.status ?? 200}`);
|
|
})
|
|
.onError(({ error, set, code }) => {
|
|
console.error("Error processing request:", error);
|
|
if (code === "NOT_FOUND") {
|
|
set.status = 404;
|
|
return { success: false, message: "Not found" };
|
|
}
|
|
if (code === "VALIDATION") {
|
|
set.status = 422;
|
|
return { success: false, message: "Validation error" };
|
|
}
|
|
Log("ERROR", "Unhandled error:", error);
|
|
set.status = 500;
|
|
return { success: false, message: "Internal server error" };
|
|
})
|
|
.get("/health", () => ({ status: "ok", instance: INSTANCE_ID, timestamp: new Date().toISOString() }))
|
|
.get("/", () => ({ status: "ok", message: "API is running" }))
|
|
.use(bugReportRoutes)
|
|
.use(authRoutes)
|
|
.use(adminRoutes)
|
|
.listen({
|
|
port: config.port,
|
|
//@ts-ignore
|
|
maxBody: 50 * 1024 * 1024, // 50MB
|
|
});
|
|
|
|
Log(
|
|
"SERVER",
|
|
`EMLy Bug Report API running on http://localhost:${app.server?.port}`
|
|
);
|
|
|
|
// Graceful shutdown
|
|
process.on("SIGINT", async () => {
|
|
Log("SERVER", "Shutting down (SIGINT)...");
|
|
await closePool();
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on("SIGTERM", async () => {
|
|
Log("SERVER", "Shutting down (SIGTERM)...");
|
|
await closePool();
|
|
process.exit(0);
|
|
});
|