claude-code-templates 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -0
- package/package.json +26 -12
- package/src/analytics/core/ConversationAnalyzer.js +754 -0
- package/src/analytics/core/FileWatcher.js +285 -0
- package/src/analytics/core/ProcessDetector.js +242 -0
- package/src/analytics/core/SessionAnalyzer.js +597 -0
- package/src/analytics/core/StateCalculator.js +190 -0
- package/src/analytics/data/DataCache.js +550 -0
- package/src/analytics/notifications/NotificationManager.js +448 -0
- package/src/analytics/notifications/WebSocketServer.js +526 -0
- package/src/analytics/utils/PerformanceMonitor.js +455 -0
- package/src/analytics-web/assets/js/main.js +312 -0
- package/src/analytics-web/components/Charts.js +114 -0
- package/src/analytics-web/components/ConversationTable.js +437 -0
- package/src/analytics-web/components/Dashboard.js +573 -0
- package/src/analytics-web/components/SessionTimer.js +596 -0
- package/src/analytics-web/index.html +882 -49
- package/src/analytics-web/index.html.original +1939 -0
- package/src/analytics-web/services/DataService.js +357 -0
- package/src/analytics-web/services/StateService.js +276 -0
- package/src/analytics-web/services/WebSocketService.js +523 -0
- package/src/analytics.js +626 -2317
- package/src/analytics.log +0 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocketService - Handles real-time communication with the server
|
|
3
|
+
* Part of the modular frontend architecture for Phase 3
|
|
4
|
+
*/
|
|
5
|
+
class WebSocketService {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.ws = null;
|
|
8
|
+
this.url = null;
|
|
9
|
+
this.isConnected = false;
|
|
10
|
+
this.reconnectAttempts = 0;
|
|
11
|
+
this.maxReconnectAttempts = 5;
|
|
12
|
+
this.reconnectDelay = 1000;
|
|
13
|
+
this.maxReconnectDelay = 30000;
|
|
14
|
+
this.heartbeatInterval = null;
|
|
15
|
+
this.heartbeatTimeout = null;
|
|
16
|
+
|
|
17
|
+
this.eventListeners = new Map();
|
|
18
|
+
this.subscriptions = new Set();
|
|
19
|
+
this.messageQueue = [];
|
|
20
|
+
this.autoReconnect = true;
|
|
21
|
+
|
|
22
|
+
// Message ID tracking for responses
|
|
23
|
+
this.messageId = 0;
|
|
24
|
+
this.pendingMessages = new Map();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Connect to WebSocket server
|
|
29
|
+
* @param {string} url - WebSocket URL (default: current host with /ws path)
|
|
30
|
+
*/
|
|
31
|
+
connect(url = null) {
|
|
32
|
+
if (this.isConnected) {
|
|
33
|
+
console.log('🔌 WebSocket already connected');
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Auto-detect WebSocket URL if not provided
|
|
38
|
+
if (!url) {
|
|
39
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
40
|
+
const host = window.location.host;
|
|
41
|
+
this.url = `${protocol}//${host}/ws`;
|
|
42
|
+
} else {
|
|
43
|
+
this.url = url;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
try {
|
|
48
|
+
console.log(`🔌 Connecting to WebSocket: ${this.url}`);
|
|
49
|
+
this.ws = new WebSocket(this.url);
|
|
50
|
+
|
|
51
|
+
this.ws.onopen = (event) => {
|
|
52
|
+
this.handleOpen(event);
|
|
53
|
+
resolve();
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
this.ws.onmessage = (event) => {
|
|
57
|
+
this.handleMessage(event);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
this.ws.onclose = (event) => {
|
|
61
|
+
this.handleClose(event);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
this.ws.onerror = (event) => {
|
|
65
|
+
this.handleError(event);
|
|
66
|
+
if (!this.isConnected) {
|
|
67
|
+
reject(new Error('WebSocket connection failed'));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('❌ Failed to create WebSocket connection:', error);
|
|
73
|
+
reject(error);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Handle WebSocket connection open
|
|
80
|
+
* @param {Event} event - Open event
|
|
81
|
+
*/
|
|
82
|
+
handleOpen(event) {
|
|
83
|
+
console.log('✅ WebSocket connected');
|
|
84
|
+
this.isConnected = true;
|
|
85
|
+
this.reconnectAttempts = 0;
|
|
86
|
+
|
|
87
|
+
// Start heartbeat
|
|
88
|
+
this.startHeartbeat();
|
|
89
|
+
|
|
90
|
+
// Process queued messages
|
|
91
|
+
this.processMessageQueue();
|
|
92
|
+
|
|
93
|
+
// Re-subscribe to channels
|
|
94
|
+
this.resubscribeToChannels();
|
|
95
|
+
|
|
96
|
+
// Emit connection event
|
|
97
|
+
this.emit('connected', { event });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Handle WebSocket message
|
|
102
|
+
* @param {MessageEvent} event - Message event
|
|
103
|
+
*/
|
|
104
|
+
handleMessage(event) {
|
|
105
|
+
try {
|
|
106
|
+
const data = JSON.parse(event.data);
|
|
107
|
+
console.log('📨 WebSocket message received:', data.type);
|
|
108
|
+
|
|
109
|
+
// Handle different message types
|
|
110
|
+
switch (data.type) {
|
|
111
|
+
case 'connection':
|
|
112
|
+
this.handleConnectionMessage(data);
|
|
113
|
+
break;
|
|
114
|
+
case 'pong':
|
|
115
|
+
this.handlePong(data);
|
|
116
|
+
break;
|
|
117
|
+
case 'conversation_state_change':
|
|
118
|
+
this.handleConversationStateChange(data);
|
|
119
|
+
break;
|
|
120
|
+
case 'data_refresh':
|
|
121
|
+
this.handleDataRefresh(data);
|
|
122
|
+
break;
|
|
123
|
+
case 'system_status':
|
|
124
|
+
this.handleSystemStatus(data);
|
|
125
|
+
break;
|
|
126
|
+
case 'file_change':
|
|
127
|
+
this.handleFileChange(data);
|
|
128
|
+
break;
|
|
129
|
+
case 'process_change':
|
|
130
|
+
this.handleProcessChange(data);
|
|
131
|
+
break;
|
|
132
|
+
case 'subscription_confirmed':
|
|
133
|
+
case 'unsubscription_confirmed':
|
|
134
|
+
this.handleSubscriptionConfirmation(data);
|
|
135
|
+
break;
|
|
136
|
+
default:
|
|
137
|
+
// Check if it's a response to a pending message
|
|
138
|
+
if (data.messageId && this.pendingMessages.has(data.messageId)) {
|
|
139
|
+
this.handleMessageResponse(data);
|
|
140
|
+
} else {
|
|
141
|
+
this.emit('message', data);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('❌ Error parsing WebSocket message:', error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Handle WebSocket connection close
|
|
152
|
+
* @param {CloseEvent} event - Close event
|
|
153
|
+
*/
|
|
154
|
+
handleClose(event) {
|
|
155
|
+
console.log('🔌 WebSocket disconnected:', event.code, event.reason);
|
|
156
|
+
this.isConnected = false;
|
|
157
|
+
this.stopHeartbeat();
|
|
158
|
+
|
|
159
|
+
// Emit disconnection event
|
|
160
|
+
this.emit('disconnected', { event });
|
|
161
|
+
|
|
162
|
+
// Auto-reconnect if enabled
|
|
163
|
+
if (this.autoReconnect && event.code !== 1000) { // 1000 = normal closure
|
|
164
|
+
this.scheduleReconnect();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Handle WebSocket error
|
|
170
|
+
* @param {Event} event - Error event
|
|
171
|
+
*/
|
|
172
|
+
handleError(event) {
|
|
173
|
+
console.error('❌ WebSocket error:', event);
|
|
174
|
+
this.emit('error', { event });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Handle connection message
|
|
179
|
+
* @param {Object} data - Message data
|
|
180
|
+
*/
|
|
181
|
+
handleConnectionMessage(data) {
|
|
182
|
+
console.log('🎉 WebSocket connection established:', data.data.clientId);
|
|
183
|
+
this.clientId = data.data.clientId;
|
|
184
|
+
this.emit('connection_established', data.data);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Handle conversation state change
|
|
189
|
+
* @param {Object} data - Message data
|
|
190
|
+
*/
|
|
191
|
+
handleConversationStateChange(data) {
|
|
192
|
+
console.log(`🔄 Conversation state changed: ${data.data.conversationId} → ${data.data.newState}`);
|
|
193
|
+
this.emit('conversation_state_change', data.data);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Handle data refresh
|
|
198
|
+
* @param {Object} data - Message data
|
|
199
|
+
*/
|
|
200
|
+
handleDataRefresh(data) {
|
|
201
|
+
console.log('📊 Data refresh received');
|
|
202
|
+
this.emit('data_refresh', data.data);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Handle system status
|
|
207
|
+
* @param {Object} data - Message data
|
|
208
|
+
*/
|
|
209
|
+
handleSystemStatus(data) {
|
|
210
|
+
console.log('ℹ️ System status update:', data.data);
|
|
211
|
+
this.emit('system_status', data.data);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Handle file change notification
|
|
216
|
+
* @param {Object} data - Message data
|
|
217
|
+
*/
|
|
218
|
+
handleFileChange(data) {
|
|
219
|
+
console.log('📁 File change detected:', data.data);
|
|
220
|
+
this.emit('file_change', data.data);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Handle process change notification
|
|
225
|
+
* @param {Object} data - Message data
|
|
226
|
+
*/
|
|
227
|
+
handleProcessChange(data) {
|
|
228
|
+
console.log('⚡ Process change detected:', data.data);
|
|
229
|
+
this.emit('process_change', data.data);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handle subscription confirmation
|
|
234
|
+
* @param {Object} data - Message data
|
|
235
|
+
*/
|
|
236
|
+
handleSubscriptionConfirmation(data) {
|
|
237
|
+
console.log(`📡 Subscription ${data.type}:`, data.data.channel);
|
|
238
|
+
this.emit('subscription_change', data.data);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Handle pong response
|
|
243
|
+
* @param {Object} data - Message data
|
|
244
|
+
*/
|
|
245
|
+
handlePong(data) {
|
|
246
|
+
if (this.heartbeatTimeout) {
|
|
247
|
+
clearTimeout(this.heartbeatTimeout);
|
|
248
|
+
this.heartbeatTimeout = null;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Handle response to pending message
|
|
254
|
+
* @param {Object} data - Response data
|
|
255
|
+
*/
|
|
256
|
+
handleMessageResponse(data) {
|
|
257
|
+
const pending = this.pendingMessages.get(data.messageId);
|
|
258
|
+
if (pending) {
|
|
259
|
+
this.pendingMessages.delete(data.messageId);
|
|
260
|
+
if (pending.resolve) {
|
|
261
|
+
pending.resolve(data);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Send message to server
|
|
268
|
+
* @param {Object} message - Message to send
|
|
269
|
+
* @param {boolean} expectResponse - Whether to expect a response
|
|
270
|
+
* @returns {Promise} Promise that resolves with response (if expected)
|
|
271
|
+
*/
|
|
272
|
+
send(message, expectResponse = false) {
|
|
273
|
+
if (!this.isConnected) {
|
|
274
|
+
// Queue message for later
|
|
275
|
+
this.messageQueue.push({ message, expectResponse });
|
|
276
|
+
console.log('📦 Message queued (not connected):', message.type);
|
|
277
|
+
return Promise.resolve();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const messageWithId = {
|
|
281
|
+
...message,
|
|
282
|
+
messageId: expectResponse ? this.generateMessageId() : undefined,
|
|
283
|
+
timestamp: Date.now()
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
if (expectResponse) {
|
|
287
|
+
return new Promise((resolve, reject) => {
|
|
288
|
+
this.pendingMessages.set(messageWithId.messageId, { resolve, reject });
|
|
289
|
+
|
|
290
|
+
// Set timeout for response
|
|
291
|
+
setTimeout(() => {
|
|
292
|
+
if (this.pendingMessages.has(messageWithId.messageId)) {
|
|
293
|
+
this.pendingMessages.delete(messageWithId.messageId);
|
|
294
|
+
reject(new Error('WebSocket message timeout'));
|
|
295
|
+
}
|
|
296
|
+
}, 10000); // 10 second timeout
|
|
297
|
+
|
|
298
|
+
this.ws.send(JSON.stringify(messageWithId));
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
this.ws.send(JSON.stringify(messageWithId));
|
|
302
|
+
return Promise.resolve();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Subscribe to a channel
|
|
308
|
+
* @param {string} channel - Channel name
|
|
309
|
+
*/
|
|
310
|
+
subscribe(channel) {
|
|
311
|
+
this.subscriptions.add(channel);
|
|
312
|
+
return this.send({
|
|
313
|
+
type: 'subscribe',
|
|
314
|
+
channel
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Unsubscribe from a channel
|
|
320
|
+
* @param {string} channel - Channel name
|
|
321
|
+
*/
|
|
322
|
+
unsubscribe(channel) {
|
|
323
|
+
this.subscriptions.delete(channel);
|
|
324
|
+
return this.send({
|
|
325
|
+
type: 'unsubscribe',
|
|
326
|
+
channel
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Request data refresh
|
|
332
|
+
*/
|
|
333
|
+
requestRefresh() {
|
|
334
|
+
return this.send({
|
|
335
|
+
type: 'refresh_request'
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Send ping to server
|
|
341
|
+
*/
|
|
342
|
+
ping() {
|
|
343
|
+
return this.send({
|
|
344
|
+
type: 'ping'
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Add event listener
|
|
350
|
+
* @param {string} event - Event name
|
|
351
|
+
* @param {Function} callback - Callback function
|
|
352
|
+
* @returns {Function} Unsubscribe function
|
|
353
|
+
*/
|
|
354
|
+
on(event, callback) {
|
|
355
|
+
if (!this.eventListeners.has(event)) {
|
|
356
|
+
this.eventListeners.set(event, new Set());
|
|
357
|
+
}
|
|
358
|
+
this.eventListeners.get(event).add(callback);
|
|
359
|
+
|
|
360
|
+
// Return unsubscribe function
|
|
361
|
+
return () => {
|
|
362
|
+
const eventCallbacks = this.eventListeners.get(event);
|
|
363
|
+
if (eventCallbacks) {
|
|
364
|
+
eventCallbacks.delete(callback);
|
|
365
|
+
if (eventCallbacks.size === 0) {
|
|
366
|
+
this.eventListeners.delete(event);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Emit event to listeners
|
|
374
|
+
* @param {string} event - Event name
|
|
375
|
+
* @param {*} data - Event data
|
|
376
|
+
*/
|
|
377
|
+
emit(event, data) {
|
|
378
|
+
const eventCallbacks = this.eventListeners.get(event);
|
|
379
|
+
if (eventCallbacks) {
|
|
380
|
+
eventCallbacks.forEach(callback => {
|
|
381
|
+
try {
|
|
382
|
+
callback(data);
|
|
383
|
+
} catch (error) {
|
|
384
|
+
console.error(`Error in WebSocket event listener for ${event}:`, error);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Process queued messages
|
|
392
|
+
*/
|
|
393
|
+
processMessageQueue() {
|
|
394
|
+
while (this.messageQueue.length > 0 && this.isConnected) {
|
|
395
|
+
const { message, expectResponse } = this.messageQueue.shift();
|
|
396
|
+
this.send(message, expectResponse);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Re-subscribe to channels after reconnection
|
|
402
|
+
*/
|
|
403
|
+
resubscribeToChannels() {
|
|
404
|
+
this.subscriptions.forEach(channel => {
|
|
405
|
+
this.send({
|
|
406
|
+
type: 'subscribe',
|
|
407
|
+
channel
|
|
408
|
+
});
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Start heartbeat mechanism
|
|
414
|
+
*/
|
|
415
|
+
startHeartbeat() {
|
|
416
|
+
this.heartbeatInterval = setInterval(() => {
|
|
417
|
+
if (this.isConnected) {
|
|
418
|
+
this.ping();
|
|
419
|
+
|
|
420
|
+
// Set timeout for pong response
|
|
421
|
+
this.heartbeatTimeout = setTimeout(() => {
|
|
422
|
+
console.warn('💔 Heartbeat timeout - closing connection');
|
|
423
|
+
this.ws.close();
|
|
424
|
+
}, 5000); // 5 second timeout for pong
|
|
425
|
+
}
|
|
426
|
+
}, 30000); // Send ping every 30 seconds
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Stop heartbeat mechanism
|
|
431
|
+
*/
|
|
432
|
+
stopHeartbeat() {
|
|
433
|
+
if (this.heartbeatInterval) {
|
|
434
|
+
clearInterval(this.heartbeatInterval);
|
|
435
|
+
this.heartbeatInterval = null;
|
|
436
|
+
}
|
|
437
|
+
if (this.heartbeatTimeout) {
|
|
438
|
+
clearTimeout(this.heartbeatTimeout);
|
|
439
|
+
this.heartbeatTimeout = null;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Schedule reconnection attempt
|
|
445
|
+
*/
|
|
446
|
+
scheduleReconnect() {
|
|
447
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
448
|
+
console.error('❌ Max reconnection attempts reached');
|
|
449
|
+
this.emit('max_reconnects_reached');
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const delay = Math.min(
|
|
454
|
+
this.reconnectDelay * Math.pow(2, this.reconnectAttempts),
|
|
455
|
+
this.maxReconnectDelay
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
console.log(`🔄 Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts + 1}/${this.maxReconnectAttempts})`);
|
|
459
|
+
|
|
460
|
+
setTimeout(() => {
|
|
461
|
+
this.reconnectAttempts++;
|
|
462
|
+
this.connect(this.url).catch(() => {
|
|
463
|
+
// Reconnection failed, will be handled by scheduleReconnect again
|
|
464
|
+
});
|
|
465
|
+
}, delay);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Generate unique message ID
|
|
470
|
+
* @returns {string} Message ID
|
|
471
|
+
*/
|
|
472
|
+
generateMessageId() {
|
|
473
|
+
return `msg_${++this.messageId}_${Date.now()}`;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Disconnect WebSocket
|
|
478
|
+
*/
|
|
479
|
+
disconnect() {
|
|
480
|
+
this.autoReconnect = false;
|
|
481
|
+
if (this.ws) {
|
|
482
|
+
this.ws.close(1000, 'Client disconnect');
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Get connection status
|
|
488
|
+
* @returns {Object} Connection status
|
|
489
|
+
*/
|
|
490
|
+
getStatus() {
|
|
491
|
+
return {
|
|
492
|
+
isConnected: this.isConnected,
|
|
493
|
+
url: this.url,
|
|
494
|
+
clientId: this.clientId,
|
|
495
|
+
reconnectAttempts: this.reconnectAttempts,
|
|
496
|
+
subscriptions: Array.from(this.subscriptions),
|
|
497
|
+
queuedMessages: this.messageQueue.length,
|
|
498
|
+
pendingMessages: this.pendingMessages.size,
|
|
499
|
+
readyState: this.ws ? this.ws.readyState : WebSocket.CLOSED
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Set auto-reconnect behavior
|
|
505
|
+
* @param {boolean} enabled - Enable auto-reconnect
|
|
506
|
+
*/
|
|
507
|
+
setAutoReconnect(enabled) {
|
|
508
|
+
this.autoReconnect = enabled;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Clear message queue
|
|
513
|
+
*/
|
|
514
|
+
clearMessageQueue() {
|
|
515
|
+
this.messageQueue = [];
|
|
516
|
+
console.log('🗑️ Message queue cleared');
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Export for module use
|
|
521
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
522
|
+
module.exports = WebSocketService;
|
|
523
|
+
}
|