UNPKG

@arkade-os/sdk

Version:

Bitcoin wallet SDK with Taproot and Ark integration

88 lines (87 loc) 3.3 kB
/** * Dynamically imports expo/fetch with fallback to standard fetch. * @returns A fetch function suitable for SSE streaming */ export async function getExpoFetch(options) { const requireExpo = options?.requireExpo ?? false; try { const expoFetchModule = await import("expo/fetch"); console.debug("Using expo/fetch for streaming"); return expoFetchModule.fetch; } catch (error) { if (requireExpo) { throw new Error("expo/fetch is unavailable in this environment. " + "Please ensure expo/fetch is installed and properly configured."); } console.warn("Using standard fetch instead of expo/fetch. " + "Streaming may not be fully supported in some environments.", error); return fetch; } } /** * Generic SSE stream processor using fetch API with ReadableStream. * Handles SSE format parsing, buffer management, and abort signals. * * @param url - The SSE endpoint URL * @param abortSignal - Signal to abort the stream * @param fetchFn - Fetch function to use (defaults to standard fetch) * @param headers - Additional headers to send * @param parseData - Function to parse and yield data from SSE events */ export async function* sseStreamIterator(url, abortSignal, fetchFn, headers, parseData) { const fetchController = new AbortController(); const cleanup = () => fetchController.abort(); abortSignal?.addEventListener("abort", cleanup, { once: true }); try { const response = await fetchFn(url, { headers: { Accept: "text/event-stream", ...headers, }, signal: fetchController.signal, }); if (!response.ok) { throw new Error(`Unexpected status ${response.status} when fetching SSE stream`); } if (!response.body) { throw new Error("Response body is null"); } const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (!abortSignal?.aborted) { const { done, value } = await reader.read(); if (done) { break; } buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); for (let i = 0; i < lines.length - 1; i++) { const line = lines[i].trim(); if (!line) continue; if (line.startsWith("data:")) { const jsonStr = line.substring(5).trim(); if (!jsonStr) continue; try { const data = JSON.parse(jsonStr); const parsed = parseData(data); if (parsed !== null) { yield parsed; } } catch (parseError) { console.error("Failed to parse SSE data:", parseError); throw parseError; } } } buffer = lines[lines.length - 1]; } } finally { abortSignal?.removeEventListener("abort", cleanup); } }