freshroute-server
Version:
Local development server for FreshRoute extension with API mocking and extended functionality
157 lines (156 loc) • 4.57 kB
JavaScript
"use strict";
class MockServerClient {
constructor(wsUrl = "ws://localhost:3002") {
this.wsUrl = wsUrl;
this.ws = null;
this.isConnected = false;
this.mockRules = [];
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectDelay = 2e3;
this.listeners = /* @__PURE__ */ new Map();
this.isIntentionalDisconnect = false;
this.connect();
}
connect() {
try {
console.log("🔌 Connecting to FreshRoute server at:", this.wsUrl);
this.ws = new WebSocket(this.wsUrl);
this.ws.onopen = () => {
console.log("🔌 Connected to FreshRoute Server");
this.isConnected = true;
this.reconnectAttempts = 0;
this.emit("connected");
this.send({ type: "GET_MOCK_RULES" });
};
this.ws.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
this.handleMessage(data);
} catch (error) {
console.error("❌ Error parsing FreshRoute server message:", error);
}
};
this.ws.onclose = () => {
console.log("🔌 Disconnected from FreshRoute Server");
this.isConnected = false;
this.emit("disconnected");
if (!this.isIntentionalDisconnect) {
this.attemptReconnect();
} else {
console.log("🔄 Intentional disconnect, skipping reconnect attempts");
this.isIntentionalDisconnect = false;
}
};
this.ws.onerror = (error) => {
const errorMessage = `Failed to connect to WebSocket server at ${this.wsUrl}`;
console.error("❌ FreshRoute server connection error:", errorMessage);
console.error("❌ WebSocket error details:", error);
this.emit("error", { message: errorMessage, originalError: error });
};
} catch (error) {
console.error("❌ Failed to connect to FreshRoute server:", error);
this.attemptReconnect();
}
}
attemptReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`🔄 Attempting to reconnect to FreshRoute server (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);
setTimeout(() => {
this.connect();
}, this.reconnectDelay);
} else {
console.log("❌ Max reconnection attempts reached. FreshRoute server unavailable.");
this.emit("maxReconnectAttemptsReached");
}
}
handleMessage(data) {
switch (data.type) {
case "MOCK_RULES_UPDATE":
this.mockRules = data.data;
this.emit("mockRulesUpdated", this.mockRules);
break;
default:
console.log("📨 Unknown message from FreshRoute server:", data);
}
}
send(data) {
if (this.isConnected && this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
} else {
console.warn("⚠️ Cannot send message: FreshRoute server not connected");
}
}
// Mock rule management methods
addMockRule(rule) {
this.send({
type: "ADD_MOCK_RULE",
rule
});
}
updateMockRule(ruleId, rule) {
this.send({
type: "UPDATE_MOCK_RULE",
ruleId,
rule
});
}
deleteMockRule(ruleId) {
this.send({
type: "DELETE_MOCK_RULE",
ruleId
});
}
getMockRules() {
return this.mockRules;
}
// Event system
on(event, callback) {
if (!this.listeners.has(event)) {
this.listeners.set(event, []);
}
this.listeners.get(event).push(callback);
}
off(event, callback) {
if (this.listeners.has(event)) {
const callbacks = this.listeners.get(event);
const index = callbacks.indexOf(callback);
if (index > -1) {
callbacks.splice(index, 1);
}
}
}
emit(event, data) {
if (this.listeners.has(event)) {
this.listeners.get(event).forEach((callback) => {
try {
callback(data);
} catch (error) {
console.error(`❌ Error in event listener for ${event}:`, error);
}
});
}
}
// Utility methods
getConnectionStatus() {
return {
isConnected: this.isConnected,
reconnectAttempts: this.reconnectAttempts,
rulesCount: this.mockRules.length
};
}
disconnect() {
if (this.ws) {
this.isIntentionalDisconnect = true;
this.ws.close();
this.ws = null;
}
this.isConnected = false;
}
}
if (typeof module !== "undefined" && module.exports) {
module.exports = MockServerClient;
} else {
window.MockServerClient = MockServerClient;
}