import { ExchangeMessage, DevtoolsMessage, ExchangeConnectionInitMessage, } from '../types'; export interface Messenger { addMessageListener: ( cb: (m: ExchangeMessage | DevtoolsMessage) => void ) => void; sendMessage: (m: ExchangeMessage) => void; } const connectionInitMessage: ExchangeConnectionInitMessage = { source: 'exchange', type: 'connection-init', version: __pkg_version__, }; /** Create curried args for native environment. */ export const createNativeMessenger = (): Messenger => { let listeners: Function[] = []; let ws: WebSocket; let timeout: NodeJS.Timeout | undefined; const createConnection = () => { timeout = undefined; ws = new WebSocket('ws://localhost:7700'); ws.onopen = () => { ws.send(JSON.stringify(connectionInitMessage)); }; ws.onclose = () => { timeout = timeout || setTimeout(createConnection, 500); }; ws.onerror = () => { timeout = timeout || setTimeout(createConnection, 500); }; ws.onmessage = (message) => { try { if (!message.data) { return; } listeners.forEach((l) => l(JSON.parse(message.data) as ExchangeMessage | DevtoolsMessage) ); } catch (err) { console.warn(err); } }; }; createConnection(); return { addMessageListener: (cb) => { listeners = [...listeners, cb]; }, sendMessage: (message) => { ws.readyState === ws.OPEN && ws.send(JSON.stringify(message)); }, }; }; /** Create curried args for browser environment. */ export const createBrowserMessenger = (): Messenger => { let listeners: Function[] = []; window.addEventListener('message', ({ data, isTrusted }) => { if (!isTrusted || !data?.source) { return; } listeners.forEach((cb) => cb(data)); }); const addMessageListener: Messenger['addMessageListener'] = (cb) => (listeners = [...listeners, cb]); const sendMessage: Messenger['sendMessage'] = (m) => window.postMessage(JSON.parse(JSON.stringify(m)), window.location.origin); sendMessage(connectionInitMessage); return { addMessageListener, sendMessage, }; };