import express, { type Express } from "express"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { createServer as createViteServer, createLogger } from "vite"; import { type Server } from "http"; import viteConfig from "../vite.config"; import { nanoid } from "nanoid"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const viteLogger = createLogger(); export function log(message: string, source = "express") { const formattedTime = new Date().toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", second: "2-digit", hour12: true, }); console.log(`${formattedTime} [${source}] ${message}`); } export async function setupVite(app: Express, server: Server) { const serverOptions = { middlewareMode: true, hmr: { server }, allowedHosts: ["*"], }; const vite = await createViteServer({ ...viteConfig, configFile: false, customLogger: { ...viteLogger, error: (msg, options) => { console.warn('Vite error (non-fatal):', msg); // Don't exit on Vite errors - they're often non-critical }, }, server: serverOptions, appType: "custom", }); app.use(vite.middlewares); app.use("*", async (req, res, next) => { const url = req.originalUrl; try { const clientTemplate = path.resolve( __dirname, "..", "client", "index.html", ); // always reload the index.html file from disk incase it changes let template = await fs.promises.readFile(clientTemplate, "utf-8"); template = template.replace( `src="/src/main.tsx"`, `src="/src/main.tsx?v=${nanoid()}"`, ); const page = await vite.transformIndexHtml(url, template); res.status(200).set({ "Content-Type": "text/html" }).end(page); } catch (e) { vite.ssrFixStacktrace(e as Error); next(e); } }); } export function serveStatic(app: Express) { // Debug: log current working directory and __dirname console.log("🔍 Current working directory:", process.cwd()); console.log("🔍 __dirname:", __dirname); // Try multiple possible paths for the static files const possiblePaths = [ path.resolve(__dirname, "../dist/public"), path.resolve(__dirname, "public"), path.resolve(process.cwd(), "dist/public"), path.resolve(process.cwd(), "public") ]; let distPath: string | null = null; for (const testPath of possiblePaths) { console.log("🧩 Testing path:", testPath, "- exists:", fs.existsSync(testPath)); if (fs.existsSync(testPath)) { distPath = testPath; console.log("✅ Found static files at:", distPath); break; } } if (!distPath) { console.warn(`❌ Build directory not found. Tested paths:`, possiblePaths); // Fallback: serve a basic HTML response app.get('/', (_req, res) => { res.send(` KnowledgeBridge

🚀 KnowledgeBridge

✅ Server is running successfully!

Frontend build not found. The API is fully functional.

`); }); // Catch all other routes app.use("*", (_req, res) => { res.redirect('/'); }); return; } console.log("🚀 Serving static files from:", distPath); app.use(express.static(distPath)); // Explicit root route app.get("/", (_req, res) => { const indexPath = path.resolve(distPath, "index.html"); console.log("🏠 Root route: serving index.html from:", indexPath); if (fs.existsSync(indexPath)) { res.sendFile(indexPath); } else { res.status(500).send("Frontend build not found"); } }); // SPA fallback - serve index.html for non-API routes app.get("*", (req, res) => { // Don't intercept API routes if (req.path.startsWith('/api/')) { return res.status(404).json({ error: 'API endpoint not found' }); } const indexPath = path.resolve(distPath, "index.html"); console.log("🔁 Fallback serving: index.html from:", indexPath); // Verify the index.html file exists before serving if (fs.existsSync(indexPath)) { console.log("✅ index.html exists, serving file"); res.sendFile(indexPath); } else { console.error("❌ index.html not found at:", indexPath); res.status(404).send(`

❌ Frontend Not Found

Expected index.html at: ${indexPath}

Available files: ${fs.readdirSync(distPath).join(', ')}

`); } }); }