import { type Express } from "express"; import { createServer as createViteServer, createLogger } from "vite"; import { type Server } from "http"; import viteConfig from "../vite.config"; import fs from "fs"; import path from "path"; import { nanoid } from "nanoid"; import { storage } from "./storage"; const viteLogger = createLogger(); function escapeHtml(str: string): string { return str.replace(/&/g, "&").replace(/"/g, """).replace(//g, ">"); } export async function setupVite(server: Server, app: Express) { const serverOptions = { middlewareMode: true, hmr: { server, path: "/vite-hmr" }, allowedHosts: true as const, }; const vite = await createViteServer({ ...viteConfig, configFile: false, customLogger: { ...viteLogger, error: (msg, options) => { viteLogger.error(msg, options); process.exit(1); }, }, server: serverOptions, appType: "custom", }); app.use(vite.middlewares); app.use("/{*path}", async (req, res, next) => { const url = req.originalUrl; try { const clientTemplate = path.resolve( import.meta.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 articleMatch = url.match(/^\/article\/([^?#]+)/); if (articleMatch) { try { const slug = decodeURIComponent(articleMatch[1]); const article = await storage.getArticleBySlug(slug); if (article) { const host = req.get("host") || "folx.tv"; const protocol = req.get("x-forwarded-proto") || "https"; const baseUrl = `${protocol}://${host}`; const articleUrl = `${baseUrl}/article/${article.slug}`; const imageUrl = article.coverImage ? (article.coverImage.startsWith("http") ? article.coverImage : `${baseUrl}${article.coverImage}`) : ""; const ogTags = [ ``, ``, ``, ``, imageUrl ? `` : "", ``, ``, ``, ``, imageUrl ? `` : "", `${escapeHtml(article.title)} - Folx Music Television`, ].filter(Boolean).join("\n "); template = template.replace( /.*?<\/title>/, ogTags ); template = template.replace( /<meta property="og:title"[^>]*\/>\s*/, "" ); template = template.replace( /<meta property="og:description"[^>]*\/>\s*/, "" ); } } catch (e) { } } 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); } }); }