ssevents

Canonical public surface for the ssevents package.

The focused modules (ssevents/event, ssevents/encoder, ssevents/decoder, ssevents/reconnect, ssevents/validate, ssevents/limit, ssevents/heartbeat, ssevents/stream, ssevents/error) carry the actual implementation, but they are an implementation detail: external code should prefer the spellings re-exported here. This is the surface the README and the published HexDocs documentation consider authoritative, and it is the surface that follows semver — the submodule shapes may be reorganized between releases.

Reach into a submodule directly only when the facade does not yet expose what you need; in that case, opening an issue so the missing entry point can be added at this level is preferred to scattering submodule imports across user code.

Types

pub type Event =
  event.Event

Re-export of ssevents/event.EventError.

pub type EventError =
  event.EventError
pub type Item =
  event.Item
pub type Iterator(a) =
  stream.Iterator(a)
pub type IteratorStep(a) =
  stream.Step(a)
pub type Limits =
  limit.Limits
pub type SseError =
  error.SseError

Values

pub fn comment(text: String) -> event.Item
pub fn comment_checked(
  text: String,
) -> Result(event.Item, event.EventError)

Strict counterpart of comment/1: returns Error(CommentContainsControlBytes(value:)) when the comment text contains CR / LF / NUL bytes. The non-strict comment/1 silently strips these bytes; WHATWG SSE §9.2.6 has no notion of a multi-line comment, so embedded line breaks would fan out into multiple comments on the wire. (#81)

pub fn comment_text_of_item(
  item: event.Item,
) -> option.Option(String)

Return the comment text when the item is a comment, None otherwise.

pub fn comment_texts_of(items: List(event.Item)) -> List(String)

Filter a decoded item list down to its comment texts, dropping events. Pairs with events_of/1.

pub fn content_type() -> String
pub fn data(event: event.Event, data: String) -> event.Event
pub fn data_of(event: event.Event) -> String
pub fn decode(
  input: String,
) -> Result(List(event.Item), error.SseError)
pub fn decode_bytes(
  input: BitArray,
) -> Result(List(event.Item), error.SseError)
pub fn decode_bytes_with_limits(
  input: BitArray,
  limits limits: limit.Limits,
) -> Result(List(event.Item), error.SseError)
pub fn decode_stream(
  chunks: stream.Iterator(BitArray),
) -> stream.Iterator(Result(event.Item, error.SseError))
pub fn decode_stream_with_limits(
  chunks: stream.Iterator(BitArray),
  limits limits: limit.Limits,
) -> stream.Iterator(Result(event.Item, error.SseError))
pub fn decode_with_limits(
  input: String,
  limits limits: limit.Limits,
) -> Result(List(event.Item), error.SseError)
pub const default_content_type: String
pub fn default_limits() -> limit.Limits
pub fn default_line_ending() -> encoder.LineEnding
pub fn empty_iterator() -> stream.Iterator(a)
pub fn encode(event: event.Event) -> String

Encode one semantic SSE Event to its wire-format String.

Use this when you want a text representation for logging, inspection, fixtures, or a caller that still expects String.

pub fn encode_bytes(event: event.Event) -> BitArray

Encode one semantic SSE Event to its wire-format BitArray.

Use this for HTTP responses and other byte-oriented transports.

pub fn encode_item(item: event.Item) -> String

Encode one Item (either an event or a comment) to String.

pub fn encode_item_bytes(item: event.Item) -> BitArray

Encode one Item (either an event or a comment) to BitArray.

pub fn encode_item_with_line_ending(
  item: event.Item,
  line_ending: encoder.LineEnding,
) -> String
pub fn encode_items(items: List(event.Item)) -> String

Encode a whole sequence of SSE items to one String.

pub fn encode_items_bytes(items: List(event.Item)) -> BitArray

Encode a whole sequence of SSE items to one BitArray.

pub fn encode_items_with_line_ending(
  items: List(event.Item),
  line_ending: encoder.LineEnding,
) -> String
pub fn encode_stream(
  items: stream.Iterator(event.Item),
) -> stream.Iterator(BitArray)
pub fn encode_with_line_ending(
  event: event.Event,
  line_ending: encoder.LineEnding,
) -> String
pub fn error_to_string(error: error.SseError) -> String
pub fn event(event: event.Event, name: String) -> event.Event
pub fn event_checked(
  event: event.Event,
  name: String,
) -> Result(event.Event, event.EventError)

Strict counterpart of event/2: returns Error(NameContainsControlBytes(value:)) when the name contains CR / LF / NUL bytes, otherwise sets the SSE event: field name. Use when the name comes from user-typed or upstream input and silent stripping would lose data the caller cares about. (#81)

pub fn event_item(event: event.Event) -> event.Item
pub fn event_of_item(
  item: event.Item,
) -> option.Option(event.Event)

Return the event payload when the item is an event, None otherwise. Pairs with comment_text_of_item/1 for the comment side.

pub fn events_of(items: List(event.Item)) -> List(event.Event)

Filter a decoded item list down to its events, dropping comments. Convenience for the common “I just want the events” pattern after decode/1.

pub fn finish(
  state: decoder.DecodeState,
) -> Result(List(event.Item), error.SseError)
pub fn from_parts(
  event_name event_name: option.Option(String),
  data data: String,
  id id: option.Option(String),
  retry retry: option.Option(Int),
) -> event.Event
pub fn heartbeat() -> event.Item
pub fn id(event: event.Event, id: String) -> event.Event
pub fn id_checked(
  event: event.Event,
  id: String,
) -> Result(event.Event, event.EventError)

Strict counterpart of id/2: returns Error(IdContainsControlBytes(value:)) when the id contains CR / LF / NUL bytes. The strip on id is especially dangerous — id(_, "ab\u{0000}cd") produces an event with id = "abcd", silently mutating an authorisation-relevant identifier on reconnect (Last-Event-ID resume). The strict variant catches this at the builder boundary. (#81)

pub fn id_of(event: event.Event) -> option.Option(String)
pub fn is_comment(item: event.Item) -> Bool

True when the item is a :-prefixed comment line.

pub fn is_event(item: event.Item) -> Bool

Issue #77: Item-level inspection helpers exposed through the facade. The Item type is re-exported as a type alias from this module, but Gleam’s type aliases do not carry the underlying EventItem / CommentItem constructors — pattern-matching on a decoded Item therefore requires reaching into ssevents/event for the variants. These accessors let callers stay inside the facade for the common cases. True when the item is an event (carries an SSE Event payload).

pub fn iterator_from_list(items: List(a)) -> stream.Iterator(a)
pub fn iterator_next(
  iterator: stream.Iterator(a),
) -> stream.Step(a)
pub fn iterator_to_list(iterator: stream.Iterator(a)) -> List(a)
pub fn last_event_id(
  state: reconnect.ReconnectState,
) -> option.Option(String)
pub fn last_event_id_header(
  state: reconnect.ReconnectState,
) -> option.Option(#(String, String))
pub fn limits() -> limit.Limits
pub fn max_data_bytes(
  event: event.Event,
  max: Int,
) -> Result(event.Event, error.SseError)
pub fn max_data_lines(limits: limit.Limits) -> Int
pub fn max_event_bytes(limits: limit.Limits) -> Int
pub fn max_line_bytes(limits: limit.Limits) -> Int
pub fn max_retry_value(limits: limit.Limits) -> Int
pub fn message(data: String) -> event.Event
pub fn name_of(event: event.Event) -> option.Option(String)
pub fn named(name: String, data: String) -> event.Event
pub fn named_checked(
  name: String,
  data: String,
) -> Result(event.Event, event.EventError)

Strict counterpart of named/2: returns Error(NameContainsControlBytes(value:)) when the name contains CR / LF / NUL bytes. Convenience for the common new |> event_checked pipeline. (#81)

pub fn new(data: String) -> event.Event
pub fn new_decoder_with_limits(
  limits: limit.Limits,
) -> decoder.DecodeState
pub fn new_limits(
  max_line_bytes max_line_bytes: Int,
  max_event_bytes max_event_bytes: Int,
  max_data_lines max_data_lines: Int,
  max_retry_value max_retry_value: Int,
) -> limit.Limits
pub const package_name: String
pub fn push(
  state: decoder.DecodeState,
  chunk: BitArray,
) -> Result(
  #(decoder.DecodeState, List(event.Item)),
  error.SseError,
)
pub fn retry(
  event: event.Event,
  milliseconds: Int,
) -> event.Event

Set the SSE retry: reconnection time on an event.

milliseconds must be >= 0. WHATWG SSE §9.2.6 only recognises a retry value whose textual form “consists of only ASCII digits”, so a negative value would be either dropped on the wire (the leading - breaks the digits-only check) or interpreted as 0 and trigger a tight reconnect loop against the server. The builder panics on ms < 0; reach for retry_clamp/2 when the caller wants the lenient (clamp-to-0) posture.

pub fn retry_clamp(
  event: event.Event,
  milliseconds: Int,
) -> event.Event

Like retry/2, but clamps milliseconds < 0 to 0 instead of panicking. Use this when forwarding a value computed from possibly- noisy input (e.g. a CLI flag, a deserialised config) and the caller would rather “publish a spec-valid retry” than crash.

pub fn retry_interval(
  state: reconnect.ReconnectState,
) -> option.Option(Int)
pub fn retry_of(event: event.Event) -> option.Option(Int)
pub fn validate_event_name(
  name: String,
) -> Result(String, error.SseError)
pub fn validate_id(id: String) -> Result(String, error.SseError)
pub fn validate_retry(
  milliseconds: Int,
) -> Result(Int, error.SseError)
Search Document