()
| 71 | }; |
| 72 | |
| 73 | const createStaticServer = async () => { |
| 74 | const server = http.createServer(async (req, res) => { |
| 75 | try { |
| 76 | const url = new URL(req.url ?? '/', 'http://localhost'); |
| 77 | const pathname = decodeURIComponent(url.pathname); |
| 78 | |
| 79 | const requestedPath = pathname === '/' ? '/index.html' : pathname; |
| 80 | const candidateFile = path.join(distDir, requestedPath); |
| 81 | |
| 82 | const direct = await readFileIfExists(candidateFile); |
| 83 | if (direct) { |
| 84 | const ext = path.extname(candidateFile).toLowerCase(); |
| 85 | res.writeHead(200, { 'Content-Type': contentTypes[ext] ?? 'application/octet-stream' }); |
| 86 | res.end(direct); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | // Directory index fallback: /foo -> /foo/index.html |
| 91 | const dirIndex = await readFileIfExists(path.join(distDir, requestedPath, 'index.html')); |
| 92 | if (dirIndex) { |
| 93 | res.writeHead(200, { 'Content-Type': contentTypes['.html'] }); |
| 94 | res.end(dirIndex); |
| 95 | return; |
| 96 | } |
| 97 | |
| 98 | // SPA fallback for route-like requests (no extension) |
| 99 | if (!path.extname(pathname)) { |
| 100 | const spa = await readFileIfExists(path.join(distDir, 'index.html')); |
| 101 | if (spa) { |
| 102 | res.writeHead(200, { 'Content-Type': contentTypes['.html'] }); |
| 103 | res.end(spa); |
| 104 | return; |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | res.writeHead(404, { 'Content-Type': contentTypes['.txt'] }); |
| 109 | res.end('Not found'); |
| 110 | } catch (e) { |
| 111 | res.writeHead(500, { 'Content-Type': contentTypes['.txt'] }); |
| 112 | res.end('Internal error'); |
| 113 | } |
| 114 | }); |
| 115 | |
| 116 | await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); |
| 117 | const address = server.address(); |
| 118 | if (!address || typeof address === 'string') throw new Error('Failed to start server'); |
| 119 | |
| 120 | return { server, port: address.port }; |
| 121 | }; |
| 122 | |
| 123 | const outputPathForRoute = (route) => { |
| 124 | if (route === '/') return path.join(distDir, 'index.html'); |
no test coverage detected