first commit
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* HMR hub — tracks connected browser HMR sockets and broadcasts update events.
|
||||
*
|
||||
* Each open page holds one WebSocket to `/__wrnexus/hmr`. The in-process file
|
||||
* watcher (see index.ts) classifies a change and broadcasts a typed message:
|
||||
*
|
||||
* { type: "css" } -> the browser hot-swaps the stylesheet (no reload)
|
||||
* { type: "reload" } -> the browser asks for fresh HTML over the HMR socket
|
||||
*
|
||||
* Server-logic changes (pages/api/middleware/realtime) are NOT broadcast here:
|
||||
* they require a fresh process, so the child exits and the supervisor respawns
|
||||
* it. The browser then reconnects and performs a soft DOM morph automatically.
|
||||
*/
|
||||
|
||||
export type HmrMessage = { type: "css"; version: number } | { type: "reload"; version: number };
|
||||
|
||||
/** Minimal shape of a Bun ServerWebSocket we rely on. */
|
||||
interface Socket {
|
||||
send(data: string): unknown;
|
||||
}
|
||||
|
||||
export class HmrHub {
|
||||
private sockets = new Set<Socket>();
|
||||
private version = 0;
|
||||
|
||||
add(ws: Socket): void {
|
||||
this.sockets.add(ws);
|
||||
}
|
||||
|
||||
remove(ws: Socket): void {
|
||||
this.sockets.delete(ws);
|
||||
}
|
||||
|
||||
broadcast(message: HmrMessage): void {
|
||||
const payload = JSON.stringify(message);
|
||||
for (const ws of this.sockets) {
|
||||
try {
|
||||
ws.send(payload);
|
||||
} catch {
|
||||
this.sockets.delete(ws);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this.sockets.size;
|
||||
}
|
||||
|
||||
css(): void {
|
||||
this.broadcast({ type: "css", version: ++this.version });
|
||||
}
|
||||
|
||||
reload(): void {
|
||||
this.broadcast({ type: "reload", version: ++this.version });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user