53 行
1.4 KiB
JavaScript
53 行
1.4 KiB
JavaScript
const { canReceiveEvent, toClientEvent } = require("../services/events");
|
|
|
|
const HEARTBEAT_INTERVAL_MS = 25_000;
|
|
|
|
function writeSseEvent(raw, event) {
|
|
const clientEvent = toClientEvent(event);
|
|
if (!clientEvent) {
|
|
return;
|
|
}
|
|
|
|
raw.write(`id: ${clientEvent.id}\n`);
|
|
raw.write(`event: ${clientEvent.type}\n`);
|
|
raw.write(`data: ${JSON.stringify(clientEvent)}\n\n`);
|
|
}
|
|
|
|
async function eventsRoutes(fastify) {
|
|
fastify.get(
|
|
"/events",
|
|
{
|
|
preHandler: fastify.authenticate,
|
|
},
|
|
async (request, reply) => {
|
|
const canManageInvoice = fastify.hasPermission(request.employee, "invoice.manage");
|
|
reply.hijack();
|
|
reply.raw.writeHead(200, {
|
|
"content-type": "text/event-stream; charset=utf-8",
|
|
"cache-control": "no-cache, no-transform",
|
|
"connection": "keep-alive",
|
|
"x-accel-buffering": "no",
|
|
});
|
|
reply.raw.write(": connected\n\n");
|
|
|
|
const unsubscribe = fastify.appEvents.subscribe((event) => {
|
|
if (!canReceiveEvent(request.employee, event, { canManageInvoice })) {
|
|
return;
|
|
}
|
|
writeSseEvent(reply.raw, event);
|
|
});
|
|
|
|
const heartbeat = setInterval(() => {
|
|
reply.raw.write(": heartbeat\n\n");
|
|
}, HEARTBEAT_INTERVAL_MS);
|
|
|
|
request.raw.on("close", () => {
|
|
clearInterval(heartbeat);
|
|
unsubscribe();
|
|
});
|
|
},
|
|
);
|
|
}
|
|
|
|
module.exports = eventsRoutes;
|