|
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); |
|
|
|
}, |
|
}, |
|
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", |
|
); |
|
|
|
|
|
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) { |
|
|
|
console.log("π Current working directory:", process.cwd()); |
|
console.log("π __dirname:", __dirname); |
|
|
|
|
|
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); |
|
|
|
|
|
app.get('/', (_req, res) => { |
|
res.send(` |
|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<title>KnowledgeBridge</title> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<style> |
|
body { font-family: system-ui, sans-serif; margin: 0; padding: 2rem; background: #f8fafc; } |
|
.container { max-width: 800px; margin: 0 auto; text-align: center; } |
|
.status { background: #10b981; color: white; padding: 1rem; border-radius: 8px; margin: 2rem 0; } |
|
.api-links { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } |
|
a { color: #3b82f6; text-decoration: none; } |
|
a:hover { text-decoration: underline; } |
|
</style> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1>π KnowledgeBridge</h1> |
|
<div class="status">β
Server is running successfully!</div> |
|
<div class="api-links"> |
|
<h3>API Endpoints Available:</h3> |
|
<p><a href="/api/health">Health Check</a></p> |
|
<p><a href="/api/documents">Documents API</a></p> |
|
<p>POST /api/search - Search endpoint</p> |
|
<p>POST /api/analyze-document - Document analysis</p> |
|
<p>POST /api/enhance-query - Query enhancement</p> |
|
</div> |
|
<p><em>Frontend build not found. The API is fully functional.</em></p> |
|
</div> |
|
</body> |
|
</html> |
|
`); |
|
}); |
|
|
|
|
|
app.use("*", (_req, res) => { |
|
res.redirect('/'); |
|
}); |
|
|
|
return; |
|
} |
|
|
|
console.log("π Serving static files from:", distPath); |
|
app.use(express.static(distPath)); |
|
|
|
|
|
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"); |
|
} |
|
}); |
|
|
|
|
|
app.get("*", (req, res) => { |
|
|
|
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); |
|
|
|
|
|
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(` |
|
<h1>β Frontend Not Found</h1> |
|
<p>Expected index.html at: ${indexPath}</p> |
|
<p>Available files: ${fs.readdirSync(distPath).join(', ')}</p> |
|
`); |
|
} |
|
}); |
|
} |
|
|