UNPKG

@zeix/ui-element

Version:

UIElement - a HTML-first library for reactive Web Components

130 lines (117 loc) • 3.49 kB
import { exec } from 'child_process' import { promisify } from 'util' import { ServerWebSocket } from 'bun' import { watch } from 'fs/promises' const execAsync = promisify(exec) const sockets = new Set<ServerWebSocket>() // Function to rebuild docs and notify clients async function rebuildDocs() { console.log('\nšŸ”„ Rebuilding docs...') const startTime = performance.now() try { await execAsync('bun run build:docs-html') const duration = (performance.now() - startTime).toFixed(2) console.log(`✨ Docs rebuilt successfully in ${duration}ms!`) // Notify all connected clients to reload sockets.forEach(socket => { socket.send('reload') }) } catch (error) { console.error('āŒ Error rebuilding docs:', error) } } // Watch for changes in markdown files async function watchDocs() { console.log('šŸ‘€ Watching for changes in docs-src/pages...') const watcher = watch('docs-src/pages', { recursive: true }) for await (const event of watcher) { if (event.filename?.endsWith('.md')) { console.log(`\nšŸ“ Detected change in: ${event.filename}`) await rebuildDocs() } } } // Start the watcher watchDocs().catch(console.error) const server = Bun.serve({ port: 3000, websocket: { open(ws: ServerWebSocket) { console.log('šŸ”Œ Client connected') sockets.add(ws) }, close(ws: ServerWebSocket) { console.log('šŸ”Œ Client disconnected') sockets.delete(ws) }, message(_ws: ServerWebSocket, message: string) { console.log('šŸ“Ø Received message:', message) }, }, async fetch(req) { const url = new URL(req.url) const path = url.pathname // Handle WebSocket upgrade if (path === '/ws') { const upgraded = server.upgrade(req) if (!upgraded) { return new Response('Upgrade failed', { status: 400 }) } return new Response() } // Inject the reload script into HTML responses if (path.endsWith('.html') || path === '/') { try { let content = await Bun.file( `./docs${path === '/' ? '/index.html' : path}`, ).text() const reloadScript = ` <script> const ws = new WebSocket('ws://' + window.location.host + '/ws'); ws.onmessage = (event) => { if (event.data === 'reload') { console.log('šŸ”„ Reloading page...'); window.location.reload(); } }; </script> ` content = content.replace('</body>', `${reloadScript}</body>`) return new Response(content, { headers: { 'Content-Type': 'text/html; charset=UTF-8' }, }) } catch (error) { console.warn(`āš ļø Not found: ${path}, Error: ${error.message}`) return new Response('Fallback response') } } // Handle other static files const type = (path: string) => { const ext = path.split('.').pop() switch (ext) { case 'js': return 'application/javascript; charset=UTF-8' case 'css': return 'text/css; charset=UTF-8' case 'png': return 'image/png' default: return 'text/html; charset=UTF-8' } } try { if (!path.match(/\.(js|css|png|ico)$/)) { console.log(`🌐 Serving: ${path}`) } return new Response(await Bun.file(`./docs${path}`).bytes(), { headers: { 'Content-Type': type(path) }, }) } catch (error) { console.warn(`āš ļø Not found: ${path}, Error: ${error.message}`) return new Response('Fallback response') } }, }) console.log(`\nšŸš€ Server started at http://localhost:${server.port}`) console.log('ā™Øļø Hot Module Reloading is enabled\n') export {}