@simpill/events.utils
v1.0.0
Published
PubSub, observer, and typed event emitter (Node and Edge).
Maintainers
Readme
Features: Type-safe · Node & Edge · Tree-shakeable
Installation
From npm
npm install @simpill/events.utilsFrom GitHub
To use this package from the monorepo source:
git clone https://github.com/SkinnnyJay/simpill.git
cd simpill/utils/@simpill-events.utils
npm install && npm run buildIn your project you can then install from the local path:
npm install /path/to/simpill/utils/@simpill-events.utils
or use npm link from the package directory.
Quick Start
import {
createPubSub,
createObservable,
createEventEmitter,
} from "@simpill/events.utils";
// PubSub: channel-based messaging (subscribe by channel name)
const pubsub = createPubSub<string>();
const unsub = pubsub.subscribe("alerts", (msg) => console.log(msg));
pubsub.publish("alerts", "hello");
// Observable: reactive value with getValue/setValue (or get/set)
const obs = createObservable(0);
obs.subscribe((n) => console.log(n));
obs.setValue(1);
obs.get(); // 1
// EventEmitter: typed events (single payload per event; use undefined for no payload)
type Events = { message: string; tick: undefined };
const emitter = createEventEmitter<Events>();
emitter.on("message", (msg) => console.log(msg));
emitter.emit("message", "hi");
emitter.emit("tick", undefined);Features
| Feature | Description |
|---------|-------------|
| PubSub | subscribe(channel, handler), publish(channel, payload), listenerCount, clearChannel, clear |
| TypedPubSub | Type-safe per-channel payloads via createTypedPubSub<ChannelMap> |
| Observable | subscribe, getValue/get, setValue/set, update(fn), emitOnSubscribe option |
| EventEmitter | Typed events: on, once, off, emit (single payload per event), listenerCount, clear; optional onError. Use payload type [A, B] or { a, b } for multiple args. |
Import Paths
import { ... } from "@simpill/events.utils"; // Everything
import { ... } from "@simpill/events.utils/client"; // Client
import { ... } from "@simpill/events.utils/server"; // Server
import { ... } from "@simpill/events.utils/shared"; // Shared onlyAPI Reference
- createPubSub<T>(options?) → PubSub<T> — subscribe(channel, handler), publish(channel, payload), listenerCount, clearChannel, clear
- createTypedPubSub<M>(options?) → TypedPubSub<M> — M is ChannelMap (channel name → payload type)
- createObservable<T>(initial, options?) → Observable<T> — getValue/get, setValue/set, update, subscribe(listener, { emitOnSubscribe? })
- createEventEmitter<M>(options?) → EventEmitter<M> — M is EventMap (event key → single payload); on, once, off, emit, listenerCount, clear
- EventEmitterOptions — onError?(event, err); PubSubOptions — onError?(channel, err); ObservableOptions — onError?(err). Default is a no-op (no console). Provide onError to log or forward handler errors.
- SubscribeOptions — emitOnSubscribe?: boolean — if true, the listener is invoked immediately with the current value when you call subscribe (Observable only).
- Unsubscribe, Listener, TypedEventEmitter, ChannelMap
Single payload and “multi-arg”
EventEmitter and PubSub use a single payload per event/channel. For multiple arguments, use one payload that is an object or tuple, e.g. type Events = { data: [string, number] }; emit("data", ["a", 1]).
Wildcards
There is no wildcard subscription (e.g. subscribe("*", ...)). Subscribe to explicit channel/event names; use a small facade if you need to fan out to multiple channels.
Minimal Observable
This Observable is minimal: get/set value and subscribe(listener). No operators, no completion, no RxJS-style streams. Use emitOnSubscribe so new subscribers get the current value immediately.
Async and backpressure
Handlers are invoked synchronously during emit/publish/setValue. If a handler is async or does heavy work, run it in a fire-and-forget or queue it yourself; this package does not provide backpressure or async dispatch.
Max listeners
There is no setMaxListeners or “possible memory leak” warning. Track listenerCount yourself if you need to guard against runaway subscriptions.
Promise-based “once”
once(event, handler) is callback-based. For a promise that resolves on first emit:const p = new Promise<T>(res => emitter.once("event", res));
What we don't provide
- Wildcard subscriptions — No
subscribe("*", ...); subscribe to explicit channel/event names. - RxJS-style operators — Observable is get/set/subscribe only; no map, filter, or streams.
- Backpressure / async dispatch — Handlers run synchronously; queue or fire-and-forget async work yourself.
- setMaxListeners / leak warning — No built-in cap or warning; use listenerCount to guard if needed.
Examples
npx ts-node examples/01-basic-usage.ts| Example | Description | |---------|-------------| | 01-basic-usage.ts | PubSub subscribe/publish, Observable get/set/subscribe, EventEmitter on/emit (single payload) |
Development
npm install
npm test
npm run build
npm run verifyDocumentation
- Examples: examples/ — run with
npx ts-node examples/01-basic-usage.ts. - Monorepo: CONTRIBUTING for creating and maintaining packages.
- README standard: Package README standard.
License
ISC
