- Install @biomejs/biome as devDependency at root - Configure biome.json with 2-space indent, double quotes, Tailwind CSS support - Add lint/lint:fix/format/format:fix scripts to root and app package.json - Fix noNonNullAssertion: env vars extracted to variables with suppression, <div role=button> replaced with <button> - Fix noUnusedVariables: remove unused destructured vars - Fix useIterableCallbackReturn: arrow functions with block body - Fix noExplicitAny: recharts Tooltip formatters - Fix noLabelWithoutControl: add htmlFor+id or use <span> for non-input labels - Fix noStaticElementInteractions/useKeyWithClickEvents: role+keyboard events for overlays - Fix noArrayIndexKey: use error string as key - Fix CSS parse: enable tailwindDirectives parser - Normalize formatting across 80 files with biome check --write
52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
import type { Context } from "hono";
|
|
import { eventBus } from "../../../lib/event-bus";
|
|
|
|
export function quoteEvents(c: Context) {
|
|
const cleanups: (() => void)[] = [];
|
|
let isCancelled = false;
|
|
|
|
function cleanup() {
|
|
if (isCancelled) return;
|
|
isCancelled = true;
|
|
cleanups.forEach((fn) => {
|
|
fn();
|
|
});
|
|
}
|
|
|
|
const stream = new ReadableStream({
|
|
start(controller) {
|
|
const unsubscribe = eventBus.on("quotes-updated", () => {
|
|
const data = "event: quotes-updated\ndata: updated\n\n";
|
|
try {
|
|
controller.enqueue(new TextEncoder().encode(data));
|
|
} catch {
|
|
/* stream closed */
|
|
}
|
|
});
|
|
cleanups.push(unsubscribe);
|
|
|
|
const keepAlive = setInterval(() => {
|
|
try {
|
|
controller.enqueue(new TextEncoder().encode(": keepalive\n\n"));
|
|
} catch {
|
|
clearInterval(keepAlive);
|
|
}
|
|
}, 5_000);
|
|
cleanups.push(() => clearInterval(keepAlive));
|
|
|
|
c.req.raw.signal.addEventListener("abort", cleanup);
|
|
},
|
|
cancel() {
|
|
cleanup();
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
"Content-Type": "text/event-stream",
|
|
"Cache-Control": "no-cache",
|
|
Connection: "keep-alive",
|
|
},
|
|
});
|
|
}
|