fetch-event-stream
Version:
A tiny (736b) utility for Server Sent Event (SSE) streaming via `fetch` and Web Streams API
56 lines (55 loc) • 2.19 kB
JavaScript
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
Object.defineProperty(exports, "__esModule", { value: true });
exports.TextLineStream = void 0;
/**
* Transform a stream into a stream where each chunk is divided by a newline,
* be it `\n` or `\r\n`. `\r` can be enabled via the `allowCR` option.
*
* @example
* ```ts
* import { TextLineStream } from "@std/streams/text-line-stream";
*
* const res = await fetch("https://example.com");
* const lines = res.body!
* .pipeThrough(new TextDecoderStream())
* .pipeThrough(new TextLineStream());
* ```
*/
class TextLineStream extends TransformStream {
#currentLine = "";
/** Constructs a new instance. */
constructor(options = { allowCR: false }) {
super({
transform: (chars, controller) => {
chars = this.#currentLine + chars;
while (true) {
const lfIndex = chars.indexOf("\n");
const crIndex = options.allowCR ? chars.indexOf("\r") : -1;
if (crIndex !== -1 && crIndex !== (chars.length - 1) &&
(lfIndex === -1 || (lfIndex - 1) > crIndex)) {
controller.enqueue(chars.slice(0, crIndex));
chars = chars.slice(crIndex + 1);
continue;
}
if (lfIndex === -1)
break;
const endIndex = chars[lfIndex - 1] === "\r" ? lfIndex - 1 : lfIndex;
controller.enqueue(chars.slice(0, endIndex));
chars = chars.slice(lfIndex + 1);
}
this.#currentLine = chars;
},
flush: (controller) => {
if (this.#currentLine === "")
return;
const currentLine = options.allowCR && this.#currentLine.endsWith("\r")
? this.#currentLine.slice(0, -1)
: this.#currentLine;
controller.enqueue(currentLine);
},
});
}
}
exports.TextLineStream = TextLineStream;
;