Files
KrisHD_AI/public/js/sse.js
T
Fretux 10ec76d437
CI / check (22) (push) Failing after 15m52s
CI / check (24) (push) Failing after 15m49s
Add browser security headers, implement upload temp directory management, and enhance SSE handling.
2026-10-07 00:54:58 +02:00

51 lines
1.8 KiB
JavaScript

/** Reusable Server-Sent Events parser for browser and test environments. */
export class SseParseError extends Error {
constructor(message, details = {}) {
super(message);
this.name = "SseParseError";
Object.assign(this, details);
}
}
function parseEvent(block, {onComment, onRetry} = {}) {
if (!block) return null;
let event = "message";
const data = [];
let id;
let retry;
for (const line of block.split(/\r?\n/)) {
if (line.startsWith(":")) { onComment?.(line.slice(1).trimStart()); continue; }
const separator = line.indexOf(":");
const field = separator < 0 ? line : line.slice(0, separator);
const value = separator < 0 ? "" : line.slice(separator + 1).replace(/^ /, "");
if (field === "event") event = value;
else if (field === "data") data.push(value);
else if (field === "id" && !value.includes("\u0000")) id = value;
else if (field === "retry" && /^\d+$/.test(value)) { retry = Number(value); onRetry?.(retry); }
}
if (!data.length) return null;
return {event, data: data.join("\n"), ...(id !== undefined ? {id} : {}), ...(retry !== undefined ? {retry} : {})};
}
export function createSseParser(options = {}) {
let buffer = "";
return {
push(text) {
buffer += text;
const blocks = buffer.split(/\r?\n\r?\n/);
buffer = blocks.pop() || "";
return blocks.map(block => parseEvent(block, options)).filter(Boolean);
},
finish() {
const event = parseEvent(buffer, options);
buffer = "";
return event ? [event] : [];
}
};
}
export function parseSseData(event) {
try { return JSON.parse(event.data); }
catch (error) { throw new SseParseError("Malformed SSE JSON payload.", {cause: error, event}); }
}