import compression from "compression"; import express from "express"; import type { Express, Request, Response, NextFunction } from "express"; import morgan from "morgan"; import { createServer } from "http"; import type { ViteDevServer } from "vite"; import path from "path"; import { fileURLToPath } from "url"; import { drizzle } from "drizzle-orm/postgres-js"; import { migrate } from "drizzle-orm/postgres-js/migrator"; import postgres from "postgres"; import { logger } from "./server/logger"; // ESM module resolution helpers const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Configuration // Resolve paths relative to project root (one level up from dist/ in production, or current dir in dev) const PROJECT_ROOT = path.resolve(__dirname, ".."); const BUILD_PATH = path.join(PROJECT_ROOT, "build/server/index.js"); const CLIENT_BUILD_PATH = path.join(PROJECT_ROOT, "build/client"); const CLIENT_ASSETS_PATH = path.join(PROJECT_ROOT, "build/client/assets"); const DEVELOPMENT = process.env.NODE_ENV === "development"; const PORT = Number.parseInt(process.env.PORT || "3000", 10); async function runMigrations(): Promise { if (!process.env.DATABASE_URL) { throw new Error("DATABASE_URL is required"); } const client = postgres(process.env.DATABASE_URL); try { const db = drizzle(client); await migrate(db, { migrationsFolder: path.join(PROJECT_ROOT, "drizzle") }); logger.log("Migrations complete"); } finally { await client.end(); } } async function createAppServer(): Promise { const app: Express = express(); app.use(compression()); app.disable("x-powered-by"); if (DEVELOPMENT) { logger.log("Starting development server"); // Dynamic import Vite only in development const { createServer: createViteServer } = await import("vite"); const viteDevServer: ViteDevServer = await createViteServer({ server: { middlewareMode: true }, }); app.use(viteDevServer.middlewares); app.use(async (req: Request, res: Response, next: NextFunction) => { try { const source = await viteDevServer.ssrLoadModule("./server/app.ts"); return await source.app(req, res, next); } catch (error) { if (error instanceof Error) { viteDevServer.ssrFixStacktrace(error); } next(error); } }); } else { logger.log("Starting production server"); app.use( "/assets", express.static(CLIENT_ASSETS_PATH, { immutable: true, maxAge: "1y" }) ); app.use(morgan("tiny")); app.use(express.static(CLIENT_BUILD_PATH, { maxAge: "1h" })); // Import the built React Router app const { app: productionApp } = await import(BUILD_PATH); app.use(productionApp); } // Create HTTP server const httpServer = createServer(app); // Initialize Socket.IO const { initializeSocketIO } = await import("./server/socket"); initializeSocketIO(httpServer); // Start server httpServer.listen(PORT, () => { logger.log(`Server is running on http://localhost:${PORT}`); }); } // Start the server with error handling (DEVELOPMENT ? Promise.resolve() : runMigrations()) .then(createAppServer) .catch((error) => { logger.error("Failed to start server:", error); process.exit(1); });