@vielzeug/pulse
v1.0.5
Published
Typed WebSocket client with channel multiplexing, presence tracking, auto-reconnect, and heartbeat
Readme
@vielzeug/pulse
Typed WebSocket client with channel multiplexing, room management, reactive presence, auto-reconnect, and heartbeat — built on @vielzeug/ripple signals.
Install
pnpm add @vielzeug/pulse @vielzeug/rippleQuick Start
import { createPulse } from '@vielzeug/pulse';
import { effect } from '@vielzeug/ripple';
type ServerEvents = {
'chat:message': { user: string; text: string };
'user:joined': { userId: string };
};
type ClientEvents = {
'chat:send': { text: string };
};
const pulse = createPulse<ServerEvents, ClientEvents>('wss://api.example.com/ws', {
reconnect: { maxAttempts: 5 },
heartbeat: true,
});
// Reactive status via ripple signal
effect(() => console.log('status:', pulse.status.value));
// Typed server events
pulse.on('chat:message', ({ user, text }) => console.log(`${user}: ${text}`));
// Typed client messages
pulse.send('chat:send', { text: 'Hello!' });
// Isolated channel namespace
const notif = pulse.channel<{ alert: { level: string; msg: string } }>('notifications');
notif.on('alert', ({ level, msg }) => console.log(`[${level}] ${msg}`));
// Reactive presence tracking
const lobby = pulse.presence<{ name: string; status: string }>('lobby');
effect(() => console.log('online:', [...lobby.state.value.keys()]));
lobby.update({ name: 'Alice', status: 'active' });
// Clean disposal
using _ = pulse;Features
- Typed event maps —
TServerandTClientgenerics enforce payload types at compile time on()/once()/wait()— persistent, one-shot, and async-await subscriptionschannel()— isolated namespaces multiplexed over the shared connectionjoin()/leave()— room membership with server-confirmation promisespresence()— reactiveSignal<Map<memberId, T>>withonJoin/onLeavecallbacks- Middleware — intercept outgoing
send()calls; omitnext()to suppress - Auto-reconnect — exponential backoff, configurable
maxAttemptsanddelay - Heartbeat — ping/pong keep-alive with dead-connection detection
- Reactive signals —
pulse.statusandpulse.roomsare rippleReactives dispose()+[Symbol.dispose]— deterministic teardown viausingdeclarations
Documentation
Full docs at vielzeug.dev/pulse.
