WebSocket
Learn how to use Universal Client with WebSocket transport for real-time communication.
Type Definitions
typescript
interface WebSocketMessage {
type: string;
data: unknown;
timestamp?: number;
}
interface ChatMessage extends WebSocketMessage {
type: 'chat';
data: { user: string; message: string };
}
interface SystemMessage extends WebSocketMessage {
type: 'system';
data: { event: string; details?: unknown };
}
type Message = ChatMessage | SystemMessage;Client Setup
typescript
import { universalClient, withDelegate, withMethods } from 'universal-client';
const wsClient = universalClient(
withDelegate({
type: 'websocket',
url: 'wss://echo.websocket.org'
}),
withMethods(({ delegate }) => ({
connect: () => delegate.connect(),
disconnect: () => delegate.close(),
sendMessage: (message: string) => {
delegate.send(JSON.stringify({ type: 'chat', data: { message }, timestamp: Date.now() }));
},
sendTypedMessage: (message: Message) => {
delegate.send(JSON.stringify(message));
},
onMessage: (callback: (data: unknown) => void) => delegate.onMessage(callback),
onError: (callback: (event: Event) => void) => delegate.onError(callback),
})),
);Usage Examples
Basic Connection and Messaging
typescript
async function basicWebSocketExample(): Promise<void> {
const unsubscribe = wsClient.onMessage((data) => {
try {
const message: Message = JSON.parse(data as string);
console.log('Received:', message);
} catch (error) {
console.log('Raw message:', data);
}
});
wsClient.connect();
await new Promise(resolve => setTimeout(resolve, 1000));
wsClient.sendMessage('Hello, WebSocket!');
wsClient.sendTypedMessage({
type: 'system',
data: { event: 'user_joined', details: { userId: 123 } }
});
}Real-time Chat
typescript
interface ChatUser { id: string; name: string; }
const chatClient = universalClient(
withDelegate({ type: 'websocket', url: 'wss://your-chat-server.com' }),
withMethods(({ delegate }) => ({
connect: () => delegate.connect(),
disconnect: () => delegate.close(),
sendChatMessage: (user: ChatUser, message: string) => {
delegate.send(JSON.stringify({
type: 'chat',
data: { userId: user.id, userName: user.name, message, timestamp: Date.now() }
}));
},
joinRoom: (roomId: string, user: ChatUser) => {
delegate.send(JSON.stringify({ type: 'join', data: { roomId, user } }));
},
leaveRoom: (roomId: string) => {
delegate.send(JSON.stringify({ type: 'leave', data: { roomId } }));
},
onMessage: (callback: (data: unknown) => void) => delegate.onMessage(callback),
onError: (callback: (event: Event) => void) => delegate.onError(callback),
})),
);
const user: ChatUser = { id: '123', name: 'John' };
chatClient.connect();
const unsubMessage = chatClient.onMessage((data) => {
const message = JSON.parse(data as string);
console.log(`${message.data.userName}: ${message.data.message}`);
});
chatClient.joinRoom('general', user);
chatClient.sendChatMessage(user, 'Hello everyone!');With Interceptors
typescript
import { universalClient, withDelegate, withInterceptor, withMethods } from 'universal-client';
const wsClient = universalClient(
withDelegate({ type: 'websocket', url: 'wss://echo.websocket.org' }),
withInterceptor({
onBeforeConnect: () => console.log('Connecting...'),
onAfterConnect: () => console.log('Connected'),
onBeforeSend: (message) => console.log('Sending:', message),
onAfterSend: (message) => console.log('Sent:', message),
onBeforeClose: () => console.log('Closing...'),
onAfterClose: () => console.log('Closed'),
onError: (error) => console.error('WS error:', error),
}),
withMethods(({ delegate }) => ({
connect: () => delegate.connect(),
disconnect: () => delegate.close(),
send: (message: string) => delegate.send(message),
onMessage: (callback: (data: unknown) => void) => delegate.onMessage(callback),
})),
);With Telemetry
typescript
import { universalClient, withDelegate, withTelemetry, withMethods } from 'universal-client';
const monitoredWsClient = universalClient(
withDelegate({ type: 'websocket', url: 'wss://echo.websocket.org' }),
withTelemetry({
enableLogging: true,
enableMetrics: true,
onEvent: (event) => console.log('Telemetry:', event)
}),
withMethods(({ delegate }) => ({
connect: () => delegate.connect(),
disconnect: () => delegate.close(),
send: (message: string) => delegate.send(message),
onMessage: (callback: (data: unknown) => void) => delegate.onMessage(callback),
})),
);
monitoredWsClient.connect();
monitoredWsClient.send('test');
const metrics = monitoredWsClient.telemetry.getMetrics();Connection Monitoring with Reconnection
typescript
class WebSocketManager {
private client: typeof wsClient;
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
constructor(client: typeof wsClient) {
this.client = client;
this.client.onError(() => this.attemptReconnect());
this.client.onMessage((data) => {
this.reconnectAttempts = 0;
console.log('Message:', JSON.parse(data as string));
});
}
private attemptReconnect(): void {
if (this.reconnectAttempts >= this.maxReconnectAttempts) return;
this.reconnectAttempts++;
const delay = Math.min(1000 * (2 ** this.reconnectAttempts), 30000);
setTimeout(() => this.client.connect(), delay);
}
connect() { this.client.connect(); }
disconnect() { this.client.disconnect(); }
send(message: string) { this.client.sendMessage(message); }
}
const manager = new WebSocketManager(wsClient);
manager.connect();Production Example
typescript
import { universalClient, withDelegate, withTelemetry, withHooks, withMethods } from 'universal-client';
const productionWsClient = universalClient(
withDelegate({ type: 'websocket', url: process.env.WS_URL || 'wss://api.example.com/ws' }),
withTelemetry({
enableMetrics: true,
enableLogging: process.env.NODE_ENV !== 'production',
}),
withHooks({ onInit: () => console.log('WebSocket client initialized') }),
withMethods(({ delegate }) => ({
connect: () => delegate.connect(),
disconnect: () => delegate.close(),
sendMessage: (type: string, payload: unknown) => {
delegate.send(JSON.stringify({ type, payload, timestamp: Date.now() }));
},
onMessage: (callback: (data: unknown) => void) => delegate.onMessage(callback),
onError: (callback: (event: Event) => void) => delegate.onError(callback),
})),
);
productionWsClient.connect();
const unsubscribe = productionWsClient.onMessage((data) => console.log('Received:', data));
productionWsClient.sendMessage('ping', { timestamp: Date.now() });
process.on('SIGINT', () => {
unsubscribe();
productionWsClient.disconnect();
process.exit(0);
});