From 0043b75c95ce65bdb0c34e763999a05fbde40334 Mon Sep 17 00:00:00 2001 From: Darius Date: Thu, 5 Feb 2026 04:34:14 +0100 Subject: [PATCH] add better sse handling --- package-lock.json | 20 ++++++++++++++++++-- package.json | 1 + src/index.ts | 3 +++ src/sse/routes.ts | 27 +++++++++++++++------------ 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 07effab..fa70306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@dpu/shared": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git", + "@fastify/sse": "^0.4.0", "@fastify/swagger": "^9.6.1", "@fastify/swagger-ui": "^5.2.3", "dotenv": "^17.2.2", @@ -25,8 +26,8 @@ } }, "node_modules/@dpu/shared": { - "version": "1.5.4", - "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#8daeed6b5f6888634993f2b14d77e06b9af9720a", + "version": "1.5.5", + "resolved": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git#921882054daa8ef862ee25fc098a295d2c7f0e04", "dependencies": { "axios": "^1.7.9", "chalk": "^5.6.2", @@ -628,6 +629,21 @@ "mime": "^3" } }, + "node_modules/@fastify/sse": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@fastify/sse/-/sse-0.4.0.tgz", + "integrity": "sha512-bBV96iT2kHEw6h3i8IMkZGaqA7Gk81ugUzTNctXuE6N2BEC/qBnUuzlD/O17V43OkJP73h0/kf3Bp/asXlSuFA==", + "license": "MIT", + "dependencies": { + "fastify-plugin": "^5.0.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "fastify": "^5.x" + } + }, "node_modules/@fastify/static": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@fastify/static/-/static-9.0.0.tgz", diff --git a/package.json b/package.json index d98a31e..d701452 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "type": "module", "dependencies": { "@dpu/shared": "git+https://git.dariusbag.dev/DarDarBinks/dpu-shared.git", + "@fastify/sse": "^0.4.0", "@fastify/swagger": "^9.6.1", "@fastify/swagger-ui": "^5.2.3", "dotenv": "^17.2.2", diff --git a/src/index.ts b/src/index.ts index 15ef162..5dfd8e0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import { sseRoutes } from "./sse/routes.js"; import { SseService } from "@dpu/shared"; import { HomepageService } from "./homepage/service.js"; import { homepageRoutes } from "./homepage/routes.js"; +import fastifySSE from "@fastify/sse"; const fastify = Fastify().withTypeProvider(); @@ -73,6 +74,8 @@ await fastify.register(fastifyAxios, { }, }); +await fastify.register(fastifySSE); + const haClient = new HomeAssistantClient(fastify.axios.homeassistant); const haService = new HomeAssistantService(haClient); diff --git a/src/sse/routes.ts b/src/sse/routes.ts index 3239ab9..5ec584d 100644 --- a/src/sse/routes.ts +++ b/src/sse/routes.ts @@ -1,5 +1,6 @@ import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; -import { SseService } from "@dpu/shared"; +import { logInfo, SseEvent, SseService } from "@dpu/shared"; +import { randomUUID } from "crypto"; export async function sseRoutes( fastify: FastifyInstance, @@ -22,25 +23,27 @@ export async function sseRoutes( tags: ["sse"], hide: true }, + sse: true }, async (request, reply) => { - reply.raw.setHeader("Content-Type", "text/event-stream"); - reply.raw.setHeader("Cache-Control", "no-cache"); - reply.raw.setHeader("Connection", "keep-alive"); + reply.sse.keepAlive() - const clientId = Date.now(); - - const sendEvent = (data: unknown) => { - reply.raw.write(`data: ${JSON.stringify(data)}\n\n`); + const clientId = randomUUID(); + const sendEvent = (data: SseEvent) => { + reply.sse.send({ + data: JSON.stringify(data) + }); }; sseService.addClient({ id: clientId, send: sendEvent }); - sendEvent({ type: "connected", message: "SSE connected" }); + await reply.sse.send({ data: 'Connected' }); + logInfo(`Connection for client ${clientId} established`); - request.raw.on("close", () => { - sseService.removeClient(clientId); - }); + reply.sse.onClose(() => { + sseService.removeClient(clientId); + logInfo(`Connection for client ${clientId} closed`); + }) }, ); }