opinionated-machine
Version:
Very opinionated DI framework for fastify, built on top of awilix
168 lines (167 loc) • 4.47 kB
TypeScript
/**
* SSE (Server-Sent Events) parsing utilities.
*
* This module provides utilities for parsing SSE event streams according
* to the W3C Server-Sent Events specification.
*
* @see https://html.spec.whatwg.org/multipage/server-sent-events.html
*
* @module sseParser
*/
export type ParsedSSEEvent = {
/**
* Event ID for client reconnection via Last-Event-ID header.
* When the client reconnects, it can send this ID to resume from where it left off.
*/
id?: string;
/**
* Event type name that maps to EventSource event listeners.
* Defaults to 'message' when not specified.
*/
event?: string;
/**
* Event data payload as a string.
* For multi-line data, lines are joined with newlines.
* Typically contains JSON that should be parsed by the consumer.
*/
data: string;
/**
* Reconnection delay hint in milliseconds.
* Suggests how long the client should wait before reconnecting.
*/
retry?: number;
};
/**
* Parse SSE events from a complete text response.
*
* This function parses a complete SSE response body into individual events.
* SSE events are separated by blank lines, and each event can have multiple fields.
*
* **SSE Format:**
* ```
* id: event-id
* event: event-name
* data: line1
* data: line2
* retry: 3000
*
* ```
*
* **Field Rules:**
* - `id:` - Event ID for Last-Event-ID reconnection
* - `event:` - Event type (defaults to 'message')
* - `data:` - Event payload (multiple data lines are joined with newlines)
* - `retry:` - Reconnection delay in milliseconds
* - Lines starting with `:` are comments and ignored
*
* @param text - Raw SSE text to parse
* @returns Array of parsed events
*
* @example
* ```typescript
* // Parse a simple SSE response
* const text = `event: message
* data: {"text":"hello"}
*
* event: done
* data: {"status":"complete"}
*
* `
* const events = parseSSEEvents(text)
* // events = [
* // { event: 'message', data: '{"text":"hello"}' },
* // { event: 'done', data: '{"status":"complete"}' }
* // ]
* ```
*
* @example
* ```typescript
* // Parse events with IDs (for reconnection)
* const text = `id: 1
* event: update
* data: {"value":42}
*
* id: 2
* event: update
* data: {"value":43}
*
* `
* const events = parseSSEEvents(text)
* // Store last ID for reconnection: events[events.length - 1].id
* ```
*
* @example
* ```typescript
* // Multi-line data
* const text = `event: log
* data: Line 1
* data: Line 2
* data: Line 3
*
* `
* const events = parseSSEEvents(text)
* // events[0].data === "Line 1\nLine 2\nLine 3"
* ```
*/
export declare function parseSSEEvents(text: string): ParsedSSEEvent[];
/**
* Result of incremental SSE buffer parsing.
*/
export type ParseSSEBufferResult = {
/** Complete events parsed from the buffer */
events: ParsedSSEEvent[];
/** Remaining incomplete data to prepend to next chunk */
remaining: string;
};
/**
* Parse SSE events incrementally from a buffer.
*
* This function is designed for streaming scenarios where data arrives
* in chunks. It parses complete events and returns any incomplete data
* that should be prepended to the next chunk.
*
* **Usage Pattern:**
* 1. Append new chunk to buffer
* 2. Call parseSSEBuffer(buffer)
* 3. Process the events
* 4. Set buffer = remaining for next iteration
*
* @param buffer - Current buffer containing SSE data
* @returns Object with parsed events and remaining incomplete buffer
*
* @example
* ```typescript
* // Streaming SSE parsing with fetch
* const response = await fetch(url)
* const reader = response.body.getReader()
* const decoder = new TextDecoder()
* let buffer = ''
*
* while (true) {
* const { done, value } = await reader.read()
* if (done) break
*
* buffer += decoder.decode(value, { stream: true })
* const { events, remaining } = parseSSEBuffer(buffer)
* buffer = remaining
*
* for (const event of events) {
* console.log('Received:', event.event, JSON.parse(event.data))
* }
* }
* ```
*
* @example
* ```typescript
* // Node.js readable stream
* let buffer = ''
* stream.on('data', (chunk: Buffer) => {
* buffer += chunk.toString()
* const { events, remaining } = parseSSEBuffer(buffer)
* buffer = remaining
*
* events.forEach(event => emit('sse-event', event))
* })
* ```
*/
export declare function parseSSEBuffer(buffer: string): ParseSSEBufferResult;