UNPKG

jsonl-webstream

Version:

Lightweight library for JSON Lines web stream between browsers and Node.js environments

71 lines (70 loc) 2.1 kB
class JsonLineScanner { onChunk; onError; #fragment = ""; constructor(onChunk, onError) { this.onChunk = onChunk; this.onError = onError; } append(buffer) { this.#fragment += buffer; while (this.#scan()) ; } #scan() { const lfPos = this.#fragment.indexOf("\n"); if (lfPos === -1) return false; const json = this.#fragment.substring(0, lfPos); this.#fragment = this.#fragment.substring(lfPos + 1); try { const chunk = JSON.parse(json); this.onChunk(chunk); return true; } catch (err) { this.onError(err); return false; } } } /** * Creates a ReadableStream that parses JSON Lines from a binary stream. * Reads binary data from the provided reader, decodes it to text, and parses * each line as a JSON object of type T. * * @param reader A ReadableStreamDefaultReader providing binary data * @returns A ReadableStream that emits parsed JSON objects of type T */ export function createJsonLinesReceiver(reader) { return new ReadableStream({ start(controller) { const decoder = new TextDecoder(); const scanner = new JsonLineScanner((chunk) => { controller.enqueue(chunk); }, (err) => { controller.error(err); }); const proceed = () => { return reader .read() .then(({ done, value }) => { if (done) { scanner.append(decoder.decode()); controller.close(); return; } scanner.append(decoder.decode(value, { stream: true })); proceed(); }) .catch((err) => { controller.error(err); }); }; proceed(); }, cancel() { reader.cancel(); }, }); }