shellphone.app/app/routes/__app/sse.notifications.ts
2022-06-27 14:03:49 +02:00

59 lines
1.4 KiB
TypeScript

import type { LoaderFunction } from "@remix-run/node";
import { events } from "~/utils/events.server";
import type { NotificationPayload } from "~/utils/web-push.server";
export let loader: LoaderFunction = ({ request }) => {
if (!request.signal) {
return new Response(null, { status: 500 });
}
return new Response(
new ReadableStream({
start(controller) {
const encoder = new TextEncoder();
let keepAliveTimeout = setTimeout(keepAlive, 30 * 1000);
let closed = false;
events.addListener("notification", onNotification);
request.signal.addEventListener("abort", close);
if (request.signal.aborted) {
close();
return;
}
function onNotification(notification: NotificationPayload) {
controller.enqueue(encoder.encode(`data: ${JSON.stringify(notification)}\n\n`));
}
function keepAlive() {
if (closed) {
return;
}
controller.enqueue(encoder.encode(":\n\n"));
keepAliveTimeout = setTimeout(keepAlive, 30 * 1000);
}
function close() {
if (closed) {
return;
}
closed = true;
clearTimeout(keepAliveTimeout);
events.removeListener("notification", onNotification);
request.signal.removeEventListener("abort", close);
controller.close();
}
},
}),
{
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
},
},
);
};