Outgoing Transform
Problem
You need one deterministic policy for application messages without continuation middleware that can call next() repeatedly or leave a send outcome implicit.
Solution
Use transform to return the serialized message shape or null to filter it.
ts
import { createPulse } from '@vielzeug/pulse';
type ClientEvents = {
'chat:send': { text: string };
'debug:trace': { detail: string };
};
const pulse = createPulse<{}, ClientEvents>('wss://api.example.com/ws', {
transform: (message) => {
if (message.event.startsWith('debug:')) return null;
return {
...message,
payload: { sentAt: Date.now(), value: message.payload },
};
},
});
await pulse.connect();
pulse.send('chat:send', { text: 'Hello!' });
pulse.send('debug:trace', { detail: 'filtered' });
pulse.dispose();Pitfalls
transformis synchronous. Complete asynchronous policy decisions before callingsend().- Return
nullto filter. Every other result is serialized and sent. - Internal frames bypass the transform. Reconnect, heartbeat, room, and presence protocol frames remain reliable.