sse.js
A flexible EventSource replacement for JavaScript with POST support, custom headers, and automatic reconnection.
Repository Health
Technical Analysis
sse.js is a drop-in EventSource replacement for consuming Server-Sent Events streams in the browser, built to overcome the standard EventSource API’s core limitations: no custom headers and no support for HTTP methods other than parameterless GET. It wraps XMLHttpRequest to let you send POST requests with a payload, attach arbitrary headers like Authorization bearer tokens, and control exactly when the stream connects via a start option.
Beyond parity with EventSource, sse.js adds built-in auto-reconnect with configurable delay and retry limits, Last-Event-ID tracking for resuming interrupted streams per the SSE specification, and a full readystatechange event lifecycle. It’s a small, dependency-free library shipped as an ES module with bundled TypeScript type declarations, making it a common choice for apps that need authenticated or POST-triggered SSE streams — such as LLM token-streaming UIs — where the native EventSource simply can’t be used.
What You Get
- A fully EventSource-compatible SSE client (open, message, error, abort, readystatechange events) that can replace window.EventSource directly
- Support for POST requests with a custom payload and arbitrary request headers, including Authorization tokens
- Built-in auto-reconnect with configurable reconnectDelay and maxRetries, plus automatic Last-Event-ID header replay on reconnection
- Bundled TypeScript type declarations (types/sse.d.ts) generated directly from the JSDoc-annotated source
- A start: false option to defer connecting until stream() is explicitly called, and a close() method that cleanly aborts and disables auto-reconnect
Common Use Cases
- Streaming LLM/chat completion tokens from a POST endpoint that requires a JSON request body
- Consuming an authenticated SSE feed that needs a Bearer token or API key in a request header
- Building resilient real-time dashboards that must automatically reconnect and resume from the last received event after a network drop
- Polyfilling EventSource in environments/tests where the native browser API isn’t available or controllable
Under The Hood
Architecture
The entire client is a single constructor function (lib/sse.js) rather than an ES class — every instance method is assigned inside the constructor via this.method = function(){} closures instead of living on a shared prototype, trading a small per-instance memory cost for straightforward private-state capture (listeners, xhr, chunk buffer, retry state) with no external module boundaries to cross. Data flows in one direction through the object: stream() opens an XMLHttpRequest and wires progress/load/readystatechange/error/abort handlers, _onStreamProgress incrementally slices xhr.responseText from the last read offset and splits on the SSE double-newline separator, _parseEventChunk turns each complete chunk into a spec-shaped event object, and _markClosed centralizes teardown plus the auto-reconnect scheduling. It’s a cohesive, single-abstraction design with no internal layering — simple to reason about for a library this size, though parsing, transport, and reconnection policy all live in the one function rather than being split into separate collaborators.
Tech Stack
Zero runtime dependencies — package.json declares only devDependencies (@babel/core and @babel/preset-env for transpiling tests, Jest for the test runner, TypeScript purely to emit .d.ts/.d.ts.map declarations from the JSDoc-annotated JS via tsc --emitDeclarationOnly, no TypeScript source is authored). The package ships as a native ES module ("type": "module", main: ./lib/sse.js) with no bundling step — the published npm package is the raw source file plus generated type declarations, built on top of the browser’s native XMLHttpRequest with no other transport dependency.
Code Quality
The test suite (lib/sse.test.js) is extensive — over a thousand lines of Jest specs covering initialization, the full event lifecycle, WHATWG SSE-spec compliance (comment lines, multi-line data concatenation, id/retry field parsing, BOM stripping), auto-reconnect behavior, and Last-Event-ID replay, run against a hand-built mock XMLHttpRequest harness with jest --coverage wired into the test script. Source comments consistently cite the relevant WHATWG spec section for each parsing rule, which is unusually thorough documentation-as-code for a library this size. There’s no authored TypeScript or visible lint configuration in the repo, so type safety during development relies on JSDoc annotations rather than compiler checks, though the emitted declarations still give consumers full typing.
API Design
The standout design decision is deliberately mirroring the native EventSource shape — addEventListener, onmessage, readyState, dispatchEvent — so existing code can adopt it as a literal drop-in replacement (EventSource = SSE) with zero API-learning cost, while layering in headers, payload, method override, and reconnection behavior through one options object passed to the constructor. Getting started requires nothing beyond new SSE(url, options) — no separate setup or configuration file — and the JSDoc typedefs for options and event shapes are thorough enough to double as the API reference.
Used by 2 apps in this directory
LibreChat
Developer Tools · AI Assistants
Unite every major AI model in one self-hosted chat platform with agents, code execution, MCP tools, and enterprise authentication.
Supabase
Developer Tools · Databases · Search
The open-source Postgres development platform that replaces Firebase with authentication, real-time APIs, edge functions, storage, and vector embeddings — all built on PostgreSQL.