Skip to content

JSON events, Response helpers, and extractors

Importing the root package installs Response helpers when Response exists, and installs a ReadableStream async-iterator fallback only if needed. Existing own properties/methods are not overwritten. Loading the package in a runtime without those globals does not install a later polyfill automatically.

JSON conversion

toJsonServerSentEventStream<DATA>(stream: ServerSentEventStream, terminateDetector?): JsonServerSentEventStream<DATA> pipes SSE objects through JsonServerSentEventTransformStream<DATA>. That class wraps JsonServerSentEventTransform<DATA>, a SafeTransformer. Both constructors accept optional TerminateDetector = (event: ServerSentEvent) => boolean.

The detector runs before JSON.parse. True terminates without emitting that frame; otherwise data is parsed and event/id/retry are preserved in JsonServerSentEvent<DATA>. The generic does not validate JSON shape. With no detector, [DONE] is invalid JSON, not a built-in terminator. Invalid JSON or a throwing detector errors the stream, so the consumer's read/iteration rejects. Termination closes the readable side and cancels/errors upstream through Web Streams propagation; it is not a reconnect operation.

Response extensions

MemberResult and failure
contentTypeHeader string or null.
isEventStreamCase-insensitive, trimmed media type equals text/event-stream; parameters such as charset are allowed.
eventStream()SSE stream or null on non-SSE content type; null body still throws.
requiredEventStream()SSE stream; wrong type or null body throws EventStreamConvertError.
jsonEventStream<DATA>(detector?)JSON event stream or null on wrong type.
requiredJsonEventStream<DATA>(detector?)JSON event stream or conversion error.

These methods do not check HTTP status, clone responses, or cache conversions. Consume the body only once. EventStreamConvertError extends FetcherError and stores the original response; its constructor also accepts optional message and cause. Later parsing errors are stream failures, not necessarily this error type.

Fetcher integration

EventStreamResultExtractor returns exchange.requiredResponse.requiredEventStream(). JsonEventStreamResultExtractor returns requiredJsonEventStream() with no termination detector and any data type. For [DONE] or typed application protocols, supply a custom ResultExtractor calling requiredJsonEventStream<DATA>(detector).

Fetcher status validation finishes before extraction; malformed body/content errors at extraction or iteration must be caught by the caller. Request completion returning a stream does not mean the stream has finished.

Complete example

ts
import '@ahoo-wang/fetcher-eventstream';
import type { ResultExtractor } from '@ahoo-wang/fetcher';
import type { JsonServerSentEventStream } from '@ahoo-wang/fetcher-eventstream';

type Delta = { text: string };
const extractor: ResultExtractor<JsonServerSentEventStream<Delta>> = exchange =>
  exchange.requiredResponse.requiredJsonEventStream<Delta>(
    event => event.data === '[DONE]',
  );
void extractor;
const response = new Response('data: {"text":"hello"}\n\ndata: [DONE]\n\n', {
  headers: { 'Content-Type': 'text/event-stream; charset=utf-8' },
});
const chunks: string[] = [];
for await (const event of response.requiredJsonEventStream<Delta>(
  event => event.data === '[DONE]',
)) {
  chunks.push(event.data.text);
}
console.assert(chunks.join('') === 'hello');

Public symbols and source

SymbolImplementation
EventStreamConvertErroreventStreamConverter.ts:54
EventStreamResultExtractoreventStreamResultExtractor.ts:38
JsonEventStreamResultExtractoreventStreamResultExtractor.ts:65
TerminateDetectorjsonServerSentEventTransformStream.ts:24
JsonServerSentEventjsonServerSentEventTransformStream.ts:31
JsonServerSentEventTransformjsonServerSentEventTransformStream.ts:47
JsonServerSentEventTransformStreamjsonServerSentEventTransformStream.ts:81
JsonServerSentEventStreamjsonServerSentEventTransformStream.ts:95
toJsonServerSentEventStreamjsonServerSentEventTransformStream.ts:107

Package index

Released under the Apache License 2.0.