@urql/devtools
Version:
The official exchange for use with Urql Devtools
89 lines (75 loc) • 2.18 kB
text/typescript
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,
};
};