eventsource-parser

A fast, source-agnostic streaming parser for Server-Sent Events (SSE), used to build EventSource clients and stream LLM responses.

Library
npm
v4.1.2
515 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
72 /100 Good
Development Activity 76
Maintenance 72
Community 44
Maturity 56
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
82 /100 Excellent
Architecture 88
Code Quality 92
Innovation 82
Learning Curve 65

eventsource-parser is a low-level, streaming parser for the Server-Sent Events (SSE) protocol used by the browser EventSource API. It makes no assumptions about how you retrieve the underlying byte stream — you create a parser instance and feed it chunks of text, complete or partial, and it calls back with fully parsed messages (id, event, and data fields), reconnection retry intervals, and stream comments as they arrive. A TransformStream variant (eventsource-parser/stream) is also exported for environments that support the Streams API, letting you pipe a fetch response body directly into a stream of parsed EventSourceMessage objects.

Because it doesn’t own the transport, eventsource-parser is the building block underneath higher-level clients — its author’s own eventsource-client package, EventSource polyfills, and countless bespoke integrations for streaming LLM chat completions over SSE. Internally the parser is tuned for exactly that workload: trailing fragments are buffered and joined once rather than concatenated on every feed() call (avoiding O(N²) blowups on payloads split across many small chunks), the common single-line event shape is dispatched without ever touching the internal data buffer, and an optional maxBufferSize guards against unbounded memory growth from a server that never terminates a line.

What You Get

  • Chunk-based feed() API - pass partial or complete SSE payloads in any order and the parser accumulates state across calls until a full message is dispatched.
  • EventSourceParserStream transform - a TransformStream<string, EventSourceMessage> for piping a decoded fetch response body straight into parsed events.
  • Full SSE field support - id, event, retry, multi-line data, and comment (:) lines are all parsed per the WHATWG spec, including BOM stripping and mixed \n/\r/\r\n line endings.
  • maxBufferSize guard - caps how much unterminated data the parser will buffer, emitting a max-buffer-size-exceeded ParseError and refusing further feed() calls until reset().
  • Typed error callbacks - onError receives a typed ParseError (invalid-retry, unknown-field, max-buffer-size-exceeded) instead of throwing, so malformed streams degrade gracefully.

Common Use Cases

  • Streaming LLM chat responses - parsing token-by-token SSE output from OpenAI-, Anthropic-, or self-hosted-compatible chat completion endpoints.
  • Building a custom EventSource client - implementing reconnect logic, custom headers, or non-browser runtimes (Node.js, Deno, Bun, edge/serverless) where the native EventSource API isn’t available or flexible enough.
  • Polyfilling EventSource in environments without it - pairing the parser with a fetch-based transport to reproduce the browser API’s behavior server-side.
  • Proxying or relaying SSE streams - re-parsing and re-emitting events when building a gateway or middleware that inspects or transforms a Server-Sent Events stream in transit.

Under The Hood

Architecture

The library is split cleanly by responsibility: parse.ts implements the core state machine (createParser) that consumes string chunks and dispatches parsed fields through closures over mutable parser state (pendingFragments, data, id, eventType), stream.ts wraps that core in a TransformStream subclass (EventSourceParserStream) for Streams-API environments, types.ts defines the public ParserConfig/ParserCallbacks/EventSourceMessage contracts, and errors.ts defines a small typed ParseError class. There is no shared mutable module state — each createParser() call closes over its own buffers — and the fast path (processLines) is deliberately duplicated from the slow, spec-correct CR/LF-aware path to avoid per-chunk branching overhead; changing the core buffering strategy (fragment array vs. string concatenation) is the one change that would ripple through the whole hot path.

Tech Stack

Written in strict TypeScript (ES2018 target, ESM-only, verbatimModuleSyntax, noUncheckedIndexedAccess) with zero runtime dependencies. Builds go through tsc --build for declaration output plus a separate bundle-size check via esbuild/terser; oxlint and oxfmt (the Rust-based Oxc toolchain) handle linting and formatting instead of ESLint/Prettier; knip checks for unused exports; releases are managed with Changesets; and tests run under vitest across Node, Bun, and Deno via dedicated test:node/test:bun/test:deno scripts.

Code Quality

The test suite (parse.test.ts, stream.test.ts, plus dedicated multibyte and benchmark-fixture suites) totals roughly four times the line count of the library source itself, covering SSE edge cases like split multi-byte characters, BOM variants, mixed line terminators, and buffer-limit termination. The tsconfig.json enables an unusually strict rule set (noUnusedLocals, noPropertyAccessFromIndexSignature, noFallthroughCasesInSwitch, strict), and CI workflows (test.yml, release.yml) gate merges on lint plus the full cross-runtime test matrix. Comments throughout parse.ts explain non-obvious micro-optimizations (e.g. why buffering avoids an O(N²) trap) rather than restating what the code does.

API Design The public surface is intentionally narrow: one factory function (createParser) taking a callbacks object, plus one TransformStream subclass for the Streams-API path — there’s no class to instantiate or state to manage beyond calling feed() and, on reconnect, reset(). Getting started requires no boilerplate beyond supplying an onEvent callback, and the same callback shapes (onId, onRetry, onComment, onError) are reused identically between the callback-based and stream-based APIs, so switching between them doesn’t require relearning the message shape.

Used by 19 apps in this directory

Python
38%
Other

Open WebUI

AI Agents · AI Assistants

156,607

The extensible, privacy-first AI platform that runs Ollama, OpenAI, and any LLM backend behind a polished, feature-packed web interface.

View details
92
Repo Health
75
Technical
66
Dependency
Built with
Python 38%
Svelte 35%
JavaScript 19%
Updated 6 days ago
JavaScript
64%
AGPL 3.0

overleaf

Collaboration · Productivity

18,266

Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.

View details
84
Repo Health
80
Technical
59
Dependency
Built with
JavaScript 64%
TypeScript 30%
Updated 1 months ago
Clojure
73%
MPL 2.0

Penpot

Design Tools

61,563

Open-source design platform with GPU-accelerated canvas, native design tokens, and MCP-powered AI workflows for teams that ship fast.

View details
91
Repo Health
83
Technical
72
Dependency
Built with
Clojure 73%
Updated 1 weeks ago
Python
55%
Other

PostHog

Ab Testing Experimentation · Analytics · Developer Tools

40,397

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python 55%
TypeScript 36%
Updated 6 days ago
TypeScript
98%
Apache 2.0

rowboat

AI Assistants · AI Development

18,060

Build, test, and deploy multi-agent AI workflows with a visual editor, RAG data sources, MCP tool integration, and a production-ready REST API.

View details
88
Repo Health
72
Technical
65
Dependency
Built with
TypeScript 98%
Updated 1 weeks ago
TypeScript
99%
MIT

Sanity

CMS

6,370

Open-source headless CMS with a fully customizable React Studio, real-time collaborative editing, structured content modeling, and GROQ query language

View details
92
Repo Health
90
Technical
66
Dependency
Built with
TypeScript 99%
Updated 6 days ago
Rust
93%
Other

Tabby

AI Code Assistants

33,924

Self-hosted AI coding assistant — run GitHub Copilot-grade code completion on your own hardware with no cloud dependency.

View details
55
Repo Health
78
Technical
61
Dependency
Built with
Rust 93%
Updated 4 months ago
TypeScript
99%
Other

Teable

Databases · No Code Platforms

21,920

A no-code PostgreSQL database with spreadsheet UX, real-time collaboration, and native AI agents — built for teams that outgrow Airtable.

View details
78
Repo Health
76
Technical
62
Dependency
Built with
TypeScript 99%
Updated 1 weeks ago
HTML
68%
AGPL 3.0

ToolJet

AI Agents · Low Code Platforms · No Code Platforms

41,123

Open-source AI-native platform to build and deploy internal tools, workflows, and AI agents with a visual drag-and-drop builder and 80+ data source integrations.

View details
94
Repo Health
81
Technical
63
Dependency
Built with
HTML 68%
JavaScript 20%
Updated 6 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers