@vielzeug/pulse
v2.4.0
Published
Typed WebSocket client with channel multiplexing, presence tracking, auto-reconnect, and heartbeat
Readme
@vielzeug/pulse
Typed WebSocket sessions with explicit connection ownership, scoped channels, ref-counted rooms with reactive presence, reconnect restoration, and heartbeat support.
Install
pnpm add @vielzeug/pulse @vielzeug/rippleQuick Start
import { createPulse } from '@vielzeug/pulse';
type Schema = {
server: { 'chat:message': { text: string } };
client: { 'chat:send': { text: string } };
channels: {
chat: {
client: { send: { text: string } };
server: { message: { text: string } };
};
};
rooms: {
lobby: { presence: { name: string } };
};
};
const pulse = createPulse<Schema>('wss://api.example.com/ws', {
reconnect: true,
});
pulse.tap((event) => {
if (event.type === 'error') console.error(event.error);
if (event.type === 'status-change') console.log('status:', event.status);
});
const chat = pulse.channel('chat');
const lobby = pulse.room('lobby');
try {
await pulse.connect();
chat.send('send', { text: 'Hello!' });
await lobby.joined;
lobby.updatePresence({ name: 'Ada' });
} catch (error) {
console.error('Pulse connection failed:', error);
}
pulse.dispose();Key Behavior
- Call
connect()before sending messages or publishing presence. Room scopes can be created before connecting — joins are sent after the connection opens. - Define server events, client events, channel schemas, and room schemas at
createPulse()so named scopes are type-safe. - Each
channel()androom()call returns an independent disposable scope. Server subscriptions and room memberships use reference counting. - Reconnect restores channels, room memberships, and the last successfully published local presence state.
send()throwsPulseConnectionErrorwhile disconnected; Pulse never silently drops or buffers application messages.room()returns aRoomScopewith ajoinedpromise. When the room definition includespresence, the scope also exposes reactive presence state,updatePresence(), andonJoin()/onLeave()handlers.- Call
tap()to observe lifecycle events; Pulse reports transport and protocol errors there rather than throwing asynchronously.
Migration
See the Pulse migration guide.
