Spaces:
Sleeping
Sleeping
File size: 1,706 Bytes
14fdc5e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | import { StreamEventName } from "@/lib/types";
type SSEEvent = {
event: StreamEventName;
data: Record<string, unknown>;
};
function parseEventBlock(block: string): SSEEvent | null {
const lines = block.split("\n").map((line) => line.trim()).filter(Boolean);
if (!lines.length) {
return null;
}
let eventName: StreamEventName = "status";
const dataLines: string[] = [];
for (const line of lines) {
if (line.startsWith("event:")) {
eventName = line.replace("event:", "").trim() as StreamEventName;
continue;
}
if (line.startsWith("data:")) {
dataLines.push(line.replace("data:", "").trim());
}
}
if (!dataLines.length) {
return null;
}
const raw = dataLines.join("\n");
try {
return {
event: eventName,
data: JSON.parse(raw) as Record<string, unknown>
};
} catch {
return {
event: eventName,
data: { message: raw }
};
}
}
export async function* parseSSEStream(
stream: ReadableStream<Uint8Array>
): AsyncGenerator<SSEEvent> {
const reader = stream.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
buffer += decoder.decode(value, { stream: true });
const blocks = buffer.split("\n\n");
buffer = blocks.pop() ?? "";
for (const block of blocks) {
const parsed = parseEventBlock(block);
if (parsed) {
yield parsed;
}
}
}
if (buffer.trim()) {
const parsed = parseEventBlock(buffer);
if (parsed) {
yield parsed;
}
}
}
|