()
| 72 | } |
| 73 | |
| 74 | async function connectWS() { |
| 75 | if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) return; |
| 76 | |
| 77 | const settings = await getSettings(); |
| 78 | const url = new URL(settings.serverUrl || DEFAULT_SETTINGS.serverUrl); |
| 79 | if (settings.apiKey) { |
| 80 | url.searchParams.set("key", settings.apiKey); |
| 81 | } |
| 82 | if (settings.routeKey) { |
| 83 | url.searchParams.set("route_key", settings.routeKey); |
| 84 | } |
| 85 | if (settings.clientLabel) { |
| 86 | url.searchParams.set("client_label", settings.clientLabel); |
| 87 | } |
| 88 | |
| 89 | ws = new WebSocket(url.toString()); |
| 90 | |
| 91 | ws.onopen = () => { |
| 92 | console.log("[Flow2API] Background connected to WebSocket", url.toString()); |
| 93 | ws.send(JSON.stringify({ |
| 94 | type: "register", |
| 95 | route_key: settings.routeKey, |
| 96 | client_label: settings.clientLabel |
| 97 | })); |
| 98 | if (heartbeatInterval) clearInterval(heartbeatInterval); |
| 99 | heartbeatInterval = setInterval(() => { |
| 100 | if (ws && ws.readyState === WebSocket.OPEN) { |
| 101 | ws.send(JSON.stringify({ type: "ping" })); |
| 102 | } |
| 103 | }, 20000); |
| 104 | }; |
| 105 | |
| 106 | let tokenQueue = Promise.resolve(); |
| 107 | |
| 108 | ws.onmessage = async (event) => { |
| 109 | let data; |
| 110 | try { |
| 111 | data = JSON.parse(event.data); |
| 112 | } catch (e) { |
| 113 | return; |
| 114 | } |
| 115 | |
| 116 | if (data.type === "register_ack") { |
| 117 | console.log("[Flow2API] Registered route key:", data.route_key || "(empty)"); |
| 118 | return; |
| 119 | } |
| 120 | |
| 121 | if (data.type === "get_token") { |
| 122 | tokenQueue = tokenQueue.then(() => handleGetToken(data)).catch(err => { |
| 123 | console.error("[Flow2API] Queue Error:", err); |
| 124 | }); |
| 125 | } |
| 126 | }; |
| 127 | |
| 128 | ws.onclose = () => { |
| 129 | console.log("[Flow2API] WebSocket Closed. Reconnecting in 2s..."); |
| 130 | ws = null; |
| 131 | if (heartbeatInterval) clearInterval(heartbeatInterval); |
no test coverage detected