docs(spikes): Deno 2.9.7 + TS 7 compatibility spike and ADR-004
Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
fe3613ee8f
commit
cf85481d95
147 files changed
+15213
No files matched your search
@@ -0,0 +1,52 @@
|
||||
// Hono 4 on Deno.serve with an SSE stream + graceful shutdown.
|
||||
import { Hono } from "hono";
|
||||
import { streamSSE } from "hono/streaming";
|
||||
import { serveStatic } from "hono/deno";
|
||||
import { redact } from "@spike/x";
|
||||
|
||||
export function createApp() {
|
||||
const app = new Hono();
|
||||
app.get("/api/v1/health", (c) => c.json({ ok: true, runtime: `deno ${Deno.version.deno}`, ts: Deno.version.typescript }));
|
||||
app.get("/api/v1/redact", (c) => c.json(redact({ url: c.req.url, apiKey: "x" }) as Record<string, unknown>));
|
||||
app.get("/api/v1/events", (c) =>
|
||||
streamSSE(c, async (stream) => {
|
||||
const after = Number(c.req.query("after") ?? 0);
|
||||
let aborted = false;
|
||||
stream.onAbort(() => { aborted = true; });
|
||||
for (let i = after + 1; i <= after + 3 && !aborted; i++) {
|
||||
await stream.writeSSE({ id: String(i), event: "tick", data: JSON.stringify({ i }) });
|
||||
await stream.sleep(100);
|
||||
}
|
||||
}));
|
||||
// Endless stream: used to check how Deno.serve shutdown treats open SSE connections.
|
||||
app.get("/api/v1/forever", (c) =>
|
||||
streamSSE(c, async (stream) => {
|
||||
let i = 0;
|
||||
while (!stream.aborted && !shutdownSignal.aborted) {
|
||||
await stream.writeSSE({ id: String(++i), data: "ping" });
|
||||
await stream.sleep(200);
|
||||
}
|
||||
}));
|
||||
// Single-container mode: serve the built SPA (react-router ssr:false) from WEB_ROOT with index.html fallback.
|
||||
const webRoot = Deno.env.get("WEB_ROOT");
|
||||
if (webRoot) {
|
||||
app.use("/*", serveStatic({ root: webRoot }));
|
||||
app.get("*", serveStatic({ root: webRoot, path: "index.html" }));
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
/** App-level shutdown signal: SSE loops must observe it, otherwise graceful shutdown waits forever. */
|
||||
export const shutdownCtl = new AbortController();
|
||||
const shutdownSignal = shutdownCtl.signal;
|
||||
|
||||
if (import.meta.main) {
|
||||
const port = Number(Deno.env.get("PORT") ?? 5199);
|
||||
const ac = new AbortController();
|
||||
const server = Deno.serve({ port, hostname: Deno.env.get("HOST") ?? "127.0.0.1", signal: ac.signal, onListen: ({ port }) => console.log(`listening ${port}`) }, createApp().fetch);
|
||||
const stop = () => { console.log("shutdown"); if (Deno.env.get("CLOSE_SSE") !== "0") shutdownCtl.abort(); ac.abort(); };
|
||||
Deno.addSignalListener("SIGTERM", stop);
|
||||
Deno.addSignalListener("SIGINT", stop);
|
||||
await server.finished;
|
||||
console.log("server finished");
|
||||
}
|
||||
Reference in new issue
Block a user