Files
ttstd-infinite-canvas/web/src/lib/json-event-stream.ts

30 lines
1.1 KiB
TypeScript

type EventBuffer = { buffer: string };
/** Feed complete JSON data frames to a protocol adapter; retain a partial tail. */
export function consumeJsonEvents(state: EventBuffer, chunk: string, receive: (payload: unknown) => void, flush = false) {
state.buffer += chunk;
const input = state.buffer;
let offset = 0;
const boundaries = input.matchAll(/\r?\n\r?\n/g);
for (const boundary of boundaries) {
deliver(input.slice(offset, boundary.index), receive);
offset = boundary.index + boundary[0].length;
// Advance only after parsing succeeds, so an invalid frame isn't silently lost.
state.buffer = input.slice(offset);
}
if (flush) {
deliver(input.slice(offset), receive);
state.buffer = "";
}
}
function deliver(frame: string, receive: (payload: unknown) => void) {
const values: string[] = [];
for (const line of frame.split(/\r?\n/)) {
if (line.slice(0, 5) !== "data:") continue;
values.push(line.charAt(5) === " " ? line.slice(6) : line.slice(5));
}
const data = values.join("\n").trim();
if (data.length && data !== "[DONE]") receive(JSON.parse(data));
}