@powertoys/relay
Version:
Tab 2 tab communication on web applications
3 lines (2 loc) • 2.72 kB
JavaScript
!function(){"use strict";const e=self,t=new Map,a=new Map;function o(e){console.warn("Unregistering client:",e);const o=a.get(e);if(t.delete(e),a.delete(e),o&&o.port)try{o.port.close()}catch(e){console.error("Error closing port:",e)}r(),console.log(`Tab unregistered. Current tabs: ${a.size}`)}function s(){return Array.from(a.values()).map((e=>({tabId:e.tabId,tabName:e.tabName,lastSeen:e.lastHeartbeat})))}function r(){const e=s();t.forEach((t=>{t.postMessage({type:"TAB_LIST",tabs:e})}))}console.log(`Relay worker started at ${(new Date).toISOString()}`),e.onconnect=function(e){const n=e.ports[0];let c=null,l=!0;console.log("New connection to worker established"),n.onmessage=function(e){const b=e.data;if(l)switch(b.type){case"REGISTER":if(a.has(b.tabId)&&(console.log("Tab already registered, cleaning up old connection"),o(b.tabId)),c=b.tabId,"*"===c)return console.error("Tab ID cannot be *, use * to broadcast to all clients"),void n.close();const e={tabId:c,tabName:b.tabName,port:n,lastHeartbeat:Date.now(),isActive:!0};!function(e,a){t.forEach((t=>{t.postMessage({type:"REGISTRATION",tabId:e,tabName:a})}))}(c,b.tabName),t.set(c,n),a.set(c,e),r();break;case"TEST_URL":n.postMessage({type:"TEST_URL_RESPONSE",tabs:s().length}),n.close();break;case"HEARTBEAT":if(b.tabId&&a.has(b.tabId)){const e=a.get(b.tabId);e.lastHeartbeat=Date.now(),a.set(b.tabId,e)}else console.log("heartbeat received for unknown tab",b.tabId);break;case"GET_TAB_LIST":n.postMessage({type:"TAB_LIST",tabs:s()});break;case"REQUEST_ACTION":const i=t.get(b.targetTabId);if(i&&c)i.postMessage({type:"ACTION_REQUEST",action:b.action,requestId:b.requestId,requestorId:c,payload:b.payload});else if(c)if("*"===b.targetTabId){Array.from(t.values()).filter((e=>e!==n)).forEach((e=>{e.postMessage({type:"ACTION_REQUEST",action:b.action,requestId:b.requestId,requestorId:c,payload:b.payload})}))}else n.postMessage({type:"ACTION_ERROR",requestId:b.requestId,error:"Target tab not available"});break;case"ACTION_RESPONSE":const d=t.get(b.requestorId);d&&d.postMessage({type:"ACTION_RESULT",requestId:b.requestId,result:b.result});break;case"UNREGISTER":console.log("Explicit unregister:",b.tabId),b.tabId&&(o(b.tabId),b.tabId===c&&(l=!1))}else console.log("Port is not active, ignoring message")},n.onmessageerror=function(){console.error("Message error on port"),console.log(`Port closed for tab ${c}`),c&&l&&(o(c),l=!1)},n.start()},setInterval((function(){const e=Date.now();let t=!1;a.forEach(((a,s)=>{e-a.lastHeartbeat>15e3&&(console.log(`Stale connection detected for tab ${s}, last seen ${(e-a.lastHeartbeat)/1e3}s ago`),o(s),t=!0)})),t&&r()}),1e4),setInterval((()=>{0===a.size&&self.close()}),1e4)}();
//# sourceMappingURL=relay.worker.js.map