;(() => { let messageId = 0 const pendingCalls = new Map() function api(method, ...args) { const id = messageId++ return new Promise((resolve, reject) => { pendingCalls.set(id, { resolve, reject }) window.parent.postMessage({ id, type: 'api-call', method, args }, '*') }) } window.addEventListener('message', (event) => { if (event.data.type === 'api-response') { const { id, result, error } = event.data const pendingCall = pendingCalls.get(id) if (pendingCall) { if (error) { pendingCall.reject(new Error(error)) } else { pendingCall.resolve(result) } pendingCalls.delete(id) } } }) window.api = new Proxy( {}, { get: (target, prop) => { return (...args) => api(prop, ...args) } } ) })()