Highly ambitious ATProtocol AppView service and sdks
at main 143 lines 4.1 kB view raw
1/// <reference lib="deno.ns" /> 2 3import { allRoutes } from "./routes.ts"; 4import { serveDir } from "@std/http/file-server"; 5 6const PORT = parseInt(Deno.env.get("PORT") || "3001"); 7const VITE_DEV_SERVER = "http://localhost:5173"; // Default Vite dev server port 8 9// Check if we're in development mode (Vite dev server running) 10const isDevelopment = Deno.env.get("NODE_ENV") !== "production"; 11 12async function defaultHandler(req: Request): Promise<Response> { 13 const url = new URL(req.url); 14 15 // In development, proxy to Vite dev server 16 if (isDevelopment) { 17 try { 18 // For SPA routing: All non-API routes go to Vite 19 // Vite will handle returning index.html for unknown routes 20 const viteUrl = new URL(url.pathname + url.search, VITE_DEV_SERVER); 21 22 // Create a clean headers object without Host header 23 const proxyHeaders = new Headers(); 24 for (const [key, value] of req.headers.entries()) { 25 // Skip host and connection headers 26 if ( 27 key.toLowerCase() !== "host" && 28 key.toLowerCase() !== "connection" 29 ) { 30 proxyHeaders.set(key, value); 31 } 32 } 33 34 return await fetch(viteUrl.toString(), { 35 method: req.method, 36 headers: proxyHeaders, 37 body: 38 req.method !== "GET" && req.method !== "HEAD" ? req.body : undefined, 39 }); 40 } catch (_error) { 41 return new Response( 42 `<!DOCTYPE html> 43<html> 44<head> 45 <title>Vite Dev Server Not Running</title> 46 <style> 47 body { 48 font-family: system-ui, -apple-system, sans-serif; 49 padding: 40px; 50 max-width: 600px; 51 margin: 0 auto; 52 line-height: 1.6; 53 } 54 h1 { color: #e74c3c; } 55 code { 56 background: #f4f4f4; 57 padding: 2px 6px; 58 border-radius: 3px; 59 font-family: monospace; 60 } 61 .command { 62 background: #2c3e50; 63 color: #ecf0f1; 64 padding: 15px; 65 border-radius: 5px; 66 margin: 15px 0; 67 } 68 </style> 69</head> 70<body> 71 <h1>⚠️ Vite Dev Server Not Running</h1> 72 <p>The Deno server is running, but it can't connect to the Vite dev server at <code>${VITE_DEV_SERVER}</code>.</p> 73 <p><strong>Start the Vite dev server in a separate terminal:</strong></p> 74 <div class="command">cd frontend-v2<br>deno task dev:vite</div> 75 <p>Then refresh this page.</p> 76</body> 77</html>`, 78 { 79 status: 503, 80 headers: { "Content-Type": "text/html" }, 81 } 82 ); 83 } 84 } else { 85 // In production, serve static files from dist/ 86 // For SPA routing: return index.html for non-file requests 87 const response = await serveDir(req, { 88 fsRoot: "./dist", 89 quiet: true, 90 }); 91 92 // If file not found (404), return index.html for SPA routing 93 if (response.status === 404) { 94 const indexFile = await Deno.readFile("./dist/index.html"); 95 return new Response(indexFile, { 96 headers: { "Content-Type": "text/html" }, 97 }); 98 } 99 100 return response; 101 } 102} 103 104// Custom routing handler that directly matches routes 105async function handler(req: Request): Promise<Response> { 106 const url = new URL(req.url); 107 108 // Only log non-asset requests to reduce noise 109 if ( 110 !url.pathname.startsWith("/src/") && 111 !url.pathname.startsWith("/@") && 112 !url.pathname.includes(".js") && 113 !url.pathname.includes(".css") 114 ) { 115 console.log(`[${req.method}] ${url.pathname}`); 116 } 117 118 // Try to match against our defined routes first 119 for (const routeDef of allRoutes) { 120 const match = routeDef.pattern.exec(url); 121 if (match && req.method === routeDef.method) { 122 console.log(`✓ Matched API route: ${routeDef.method} ${url.pathname}`); 123 return await routeDef.handler(req); 124 } 125 } 126 127 // Fall back to default handler (proxy to Vite or serve static) 128 return await defaultHandler(req); 129} 130 131Deno.serve( 132 { 133 port: PORT, 134 hostname: "0.0.0.0", 135 onListen: ({ port, hostname }) => { 136 console.log(`Frontend-v2 server running on http://${hostname}:${port}`); 137 if (isDevelopment) { 138 console.log(`Proxying to Vite dev server at ${VITE_DEV_SERVER}`); 139 } 140 }, 141 }, 142 handler 143);