export function openStream(baseUrl, token, path, handlers) {
const controller = new AbortController();
let closedByUs = false;
(async () => {
let httpResponse;
try {
httpResponse = await fetch(baseUrl.replace(/\/+$/, "") + path, {
headers: token ? { Authorization: "Bearer " + token } : {},
signal: controller.signal,
});
} catch (error) {
if (!closedByUs) handlers.onError?.(error && error.message ? error.message : "falha ao conectar");
handlers.onClose?.();
return;
}
if (!httpResponse.ok || !httpResponse.body) {
handlers.onError?.("HTTP " + httpResponse.status);
handlers.onClose?.();
return;
}
const reader = httpResponse.body.getReader();
const decoder = new TextDecoder("utf-8");
let buf = "";
try {
for (;;) {
const { value, done } = await reader.read();
if (done) break;
buf += decoder.decode(value, { stream: true });
let sep;
while ((sep = buf.indexOf("\n\n")) !== -1) {
const record = buf.slice(0, sep);
buf = buf.slice(sep + 2);
let kind = "message";
let data = null;
for (const line of record.split("\n")) {
if (line.startsWith("event:")) kind = line.slice(6).trim();
else if (line.startsWith("data:")) data = line.slice(5).trim();
}
if (data !== null) {
try {
handlers.onEvent(kind, JSON.parse(data));
} catch {
}
}
}
}
} catch (error) {
if (!closedByUs) handlers.onError?.(error && error.message ? error.message : "stream interrompida");
}
if (!closedByUs) handlers.onClose?.();
})();
return {
close() {
closedByUs = true;
controller.abort();
},
};
}