/** * Server-sent events read off a `fetch` body, parsed per WHATWG HTML * § 9.2.6 "Parsing an event stream". * * Why not `EventSource`: it hides the HTTP response. A refused stream * (non-2xx) reaches it as an opaque `error` event without status or body, so * a client on it cannot tell a network drop from a `429 connection_limit` and * retries both. Off `fetch`, the response stays in the caller's hands. */ export interface ServerSentEvent { /** The `event:` field; `'message'` when the block carried none. */ type: string; /** The `data:` lines joined with `\n`, the trailing newline removed. */ data: string; /** The last event ID committed by the stream so far; `''` until an `id:` arrives. */ lastEventId: string; } /** * What survives a reconnect: the last event ID string (sent as * `Last-Event-ID`, and the ID the next connection's events carry until the * server sends a new `id:`) and the reconnection time. Owned by the * connection loop and written by every parser it creates. The parser's own * line and event buffers die with the connection — which is what "any pending * data must be discarded" at end of stream requires, with no reset step to * forget; an `id:` the dead connection never committed goes with them. */ export interface EventStreamCursor { lastEventId: string; retry: number | undefined; } export interface EventStreamParser { /** Feed one chunk of bytes; returns every event the chunk completed, in order. */ push(chunk: Uint8Array): ServerSentEvent[]; /** Last event ID string (the value to send as `Last-Event-ID` on a reconnect). */ readonly lastEventId: string; /** Reconnection time from the last `retry:` field, in ms; `undefined` until one arrives. */ readonly retry: number | undefined; } /** * One parser per connection. `cursor` is shared with the next connection's * parser; everything else here is scoped to this stream. */ export declare function createEventStreamParser(cursor?: EventStreamCursor): EventStreamParser; /** * The `Last-Event-ID` value for a `fetch` header, or `undefined` when the ID * cannot be sent as `EventSource` would send it. `EventSource` puts the ID's * UTF-8 bytes on the wire; `fetch` header values are byte strings, and the * engines disagree on how a string becomes bytes — Chromium writes one byte * per code unit (`ü` → `fc`, an emoji throws), WebKit re-encodes as UTF-8 * (measured; pre-mapping the UTF-8 bytes onto code units then double-encodes * there). ASCII is the same bytes everywhere; anything else is not sent. */ export declare function lastEventIdHeader(id: string): string | undefined; /** * Pump `body` through `parser`, handing every completed event to `onEvent`. * Resolves when the server closes the stream or `signal` aborts; rejects when * the transport fails (a real `fetch` errors the body on abort, which is why * the caller checks `signal.aborted` before treating a rejection as a drop), * or when `onEvent` throws. However the loop ends, the body is cancelled — * a connection left open by a throw would still count against the server's * per-user cap. */ export declare function readEventStream(body: ReadableStream, parser: EventStreamParser, onEvent: (event: ServerSentEvent) => void, signal: AbortSignal): Promise;