Events API

primate/events creates typed, keyed event channels within one JavaScript runtime.

import events from "primate/events";

It works in server and browser module graphs, but channels do not cross between them or between processes. See the Events guide for an SSE workflow.

events.channel()

channel<Key, Event>(): EventChannel<Key, Event>;

Creates an independent channel with no listeners. Key determines subscription routing and Event determines the emitted payload. The entrypoint has no named exports; EventChannel below is an inferred supporting type.

EventChannel

type EventChannel<Key, Event> = Readonly<{
  emit(key: Key, event: Event): void;
  subscribe(
    key: Key,
    listener: (event: Event) => void,
  ): () => void;
}>;

The object is typed read-only. Its listener registry remains private and in-memory.

channel.emit()

emit(key: Key, event: Event): void;

Synchronously invokes a snapshot of listeners subscribed to the exact key, in subscription insertion order. It returns void; emissions are not buffered or replayed. A listener may unsubscribe during emission without skipping other listeners in that emission. Listener exceptions propagate and stop that call.

channel.subscribe()

subscribe(
  key: Key,
  listener: (event: Event) => void,
): () => void;

Adds the listener to the key's Set and returns an unsubscribe function. Subscribing the same function repeatedly for the same key keeps one Set entry. Unsubscribing removes it and removes the key when no listeners remain. Calling the returned function again is a no-op.

Runtime scope

Channels are local to the module instance and memory of the runtime that created them. They do not persist, queue, broadcast between workers/processes, or bridge server and browser. Use external infrastructure when events must survive restarts or reach other application instances.