UNPKG

trpc-browser

Version:

tRPC adapters and links for everywhere in the browser

93 lines 3.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.popupLink = void 0; const constants_1 = require("../shared/constants"); const base_1 = require("./internal/base"); const popupLink = (opts) => { const messageHandlerMap = new Map(); const closeHandlerSet = new Set(); let popupWindow = null; async function getPopup(loadListenWindow) { if (!popupWindow || popupWindow.closed) { popupWindow = opts.createPopup(); await Promise.race([ // wait til window is loaded (same origin) new Promise((resolve) => { var _a; try { (_a = popupWindow === null || popupWindow === void 0 ? void 0 : popupWindow.addEventListener) === null || _a === void 0 ? void 0 : _a.call(popupWindow, 'load', resolve); } catch (_b) { // if this throws, it's a cross-origin popup and should stay pending (never resolve) } }), // this is needed for cross-origin popups as they don't have a load event new Promise((resolve) => { loadListenWindow.addEventListener('message', (event) => { if (event.data === constants_1.TRPC_BROWSER_LOADED_EVENT) { resolve(); } }); }), // expect the popup to load after 15s max, in case non of the above events fire new Promise((resolve) => { console.warn('Could not detect if popup loading succeeded after 15s timeout, continuing anyway'); setTimeout(resolve, 15000); }), ]); // subscribe to popup closing try { if (!popupWindow.addEventListener) { throw new Error('popupWindow.addEventListener is not a function'); } popupWindow.addEventListener('beforeunload', () => { popupWindow = null; }); } catch (_a) { // this throws on cross-origin popups, fallback to polling to check if popup is closed const pid = setInterval(() => { if (popupWindow && popupWindow.closed) { popupWindow = null; closeHandlerSet.forEach((handler) => { handler(); }); clearInterval(pid); } }, 1000); } } return popupWindow; } return (0, base_1.createBaseLink)({ async postMessage(message) { const popup = await getPopup(opts.listenWindow); return popup.postMessage(message, { targetOrigin: opts.postOrigin, }); }, addMessageListener(listener) { const handler = (ev) => { listener(ev.data); }; messageHandlerMap.set(listener, handler); opts.listenWindow.addEventListener('message', handler); }, removeMessageListener(listener) { const handler = messageHandlerMap.get(listener); if (handler) { opts.listenWindow.removeEventListener('message', handler); } }, addCloseListener(listener) { opts.listenWindow.addEventListener('beforeunload', listener); closeHandlerSet.add(listener); }, removeCloseListener(listener) { opts.listenWindow.removeEventListener('beforeunload', listener); closeHandlerSet.delete(listener); }, }); }; exports.popupLink = popupLink; //# sourceMappingURL=popup.js.map