@tastekim/chat-cli
Version:
💬Connect with developers worldwide through an interactive terminal chat experience while you code!💻
124 lines • 4.7 kB
JavaScript
import WebSocket from 'ws';
import { EventEmitter } from 'events';
export class WebSocketClient extends EventEmitter {
constructor(serverUrl = 'ws://34.64.54.24:8080/api/v1/ws') {
super();
this.ws = null;
this.userLocation = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectDelay = 1000;
this.isConnected = false;
this.isReconnecting = false;
this.reconnectTimeout = null;
this.serverUrl = serverUrl;
}
async connectWithParams(nickname, room, location) {
const url = new URL(this.serverUrl);
url.searchParams.set('nickname', nickname);
url.searchParams.set('room', room);
this.serverUrl = url.toString();
this.userLocation = location || null;
return this.connect();
}
async connect() {
return new Promise((resolve, reject) => {
if (this.isConnected) {
resolve();
return;
}
this.ws = new WebSocket(this.serverUrl);
const connectTimeout = setTimeout(() => {
if (this.ws)
this.ws.terminate();
reject(new Error('Connection timeout'));
}, 10000);
this.ws.on('open', () => {
console.log('WebSocket connection opened');
clearTimeout(connectTimeout);
this.isConnected = true;
this.reconnectAttempts = 0;
this.isReconnecting = false;
this.emit('connected');
resolve();
});
this.ws.on('message', (data) => {
// All messages are now handled by the ChatInterface
this.emit('message', data.toString());
});
this.ws.on('close', (code, reason) => {
clearTimeout(connectTimeout);
this.isConnected = false;
this.emit('disconnected', { code, reason: reason || 'Connection closed' });
if (code !== 1000 && !this.isReconnecting) {
this.attemptReconnect();
}
});
this.ws.on('error', (error) => {
clearTimeout(connectTimeout);
this.isConnected = false;
this.emit('error', error);
if (this.reconnectAttempts === 0) {
reject(error);
}
});
});
}
attemptReconnect() {
if (this.isReconnecting || this.reconnectAttempts >= this.maxReconnectAttempts) {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
this.emit('maxReconnectAttemptsReached');
}
return;
}
this.isReconnecting = true;
this.reconnectAttempts++;
const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000);
this.reconnectTimeout = setTimeout(async () => {
try {
await this.connect();
this.isReconnecting = false;
}
catch (error) {
this.isReconnecting = false;
this.attemptReconnect();
}
}, delay);
}
sendWebSocketMessage(message) {
// console.log('sendWebSocketMessage called with:', message);
// console.log('Connection state - isConnected:', this.isConnected);
// console.log('WebSocket readyState:', this.ws?.readyState);
// console.log('WebSocket.OPEN constant:', WebSocket.OPEN);
if (!this.isConnectionOpen()) {
console.error('Connection not open - cannot send message');
this.emit('error', new Error('Connection not available'));
return false;
}
try {
const jsonMessage = JSON.stringify(message);
// console.log('Sending JSON message:', jsonMessage);
this.ws?.send(jsonMessage);
// console.log('Message sent successfully');
return true;
}
catch (error) {
console.error('Error sending message:', error);
this.emit('error', new Error('Failed to send message'));
return false;
}
}
disconnect() {
this.isConnected = false;
this.isReconnecting = false;
if (this.reconnectTimeout)
clearTimeout(this.reconnectTimeout);
if (this.ws) {
this.ws.close(1000, 'Client disconnecting');
}
}
isConnectionOpen() {
return this.isConnected && this.ws?.readyState === WebSocket.OPEN;
}
}
//# sourceMappingURL=client.js.map