Created
February 20, 2025 22:50
-
-
Save colorincode/ea64ab7cea51a4afee38c90a410ccb30 to your computer and use it in GitHub Desktop.
serve ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { serve, HTMLBundle, Server } from "bun"; | |
import { watch } from "fs"; | |
import { join } from "path"; | |
import { buildProject, runBuild} from "./bun_build"; | |
import { URL } from "url"; | |
// const clients = new Set<new WebSocket("ws://localhost:8080")>; | |
let hostname = "localhost"; | |
const initial = performance.now(); | |
const clients = new Set<WebSocket>(); | |
let isBuilding = false; | |
type DisposableTimer = Timer & { [Symbol.dispose](): void }; | |
let buildTimeout: DisposableTimer | null = null; | |
async function findAvailablePort(startPort: number = 1234): Promise<number> { | |
for (let port = startPort; port < 65536; port++) { | |
try { | |
const testServer = Bun.serve({ | |
port, | |
fetch() { | |
return new Response("Port check"); | |
}, | |
}); | |
if (typeof testServer.stop === "function") { | |
testServer.stop(); | |
} | |
return port; | |
} catch (error: any) { | |
if (error.code !== "EADDRINUSE") { | |
throw error; | |
} | |
// If the error indicates the port is in use, continue checking. | |
} | |
} | |
throw new Error("No available ports found"); | |
} | |
// const port = await findAvailablePort() ; //call this outside of scope | |
export async function startServer() { | |
const port = await findAvailablePort(); | |
const server = Bun.serve({ | |
port: 0, | |
async fetch(req, server) { | |
// If the request can be upgraded for websockets, do so: | |
const upgradeSuccessful = server.upgrade(req); | |
const url = new URL(req.url); | |
let filePath = join("./dist", url.pathname); | |
if (url.pathname === "/" || url.pathname === "/index.html") { | |
filePath = join("./dist", "index.html"); | |
} | |
const file = Bun.file(filePath); | |
if (await file.exists() || upgradeSuccessful) { | |
return new Response(file); | |
} else { | |
return new Response("Not Found", { status: 404 }); | |
} | |
}, | |
websocket: { | |
message(ws, message) { | |
console.log(`Received message: ${message}`); | |
ws.send(`Echo: ${message}`); | |
}, | |
open(ws) { | |
clients.add(ws); | |
}, | |
close(ws) { | |
clients.delete(ws); | |
}, | |
}, | |
}); | |
console.log(`Server running at http://localhost:${port}`); | |
return server; | |
} | |
function debounce(func: Function, delay: number) { | |
let timeoutId: ReturnType<typeof setTimeout> | null = null; | |
return (...args: any[]) => { | |
if (timeoutId) { | |
clearTimeout(timeoutId); | |
} | |
timeoutId = setTimeout(() => func(...args), delay); | |
}; | |
} | |
// function debounce(func: Function, delay: number) { | |
// let timeoutId: Timer | null = null; | |
// return (...args: any[]) => { | |
// if (timeoutId) { | |
// clearTimeout(timeoutId); | |
// } | |
// timeoutId = setTimeout(() => { | |
// func(...args); | |
// }, delay); | |
// }; | |
// } | |
const debouncedBuild = debounce(async () => { | |
if (!isBuilding) { | |
isBuilding = true; | |
console.log("Starting build..."); | |
await buildProject(); | |
isBuilding = false; | |
clients.forEach(client => client.send("reload")); | |
} | |
}, 1000); | |
function watchAndRebuild() { | |
const srcDir = join(process.cwd(), "src"); | |
watch(srcDir, { recursive: true }, (event, filename) => { | |
console.log(`File changed: ${filename}`); | |
debouncedBuild(); | |
}); | |
} | |
async function main() { | |
await buildProject(); | |
await startServer(); | |
watchAndRebuild(); | |
} | |
main().catch(console.error); | |
console.log("Buns are in the oven."); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment