UNPKG

async-post-message

Version:

Asynchronous postMessage protocol for typed, promise-based windows and iFrame communication

154 lines (150 loc) 4.6 kB
var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // src/ParentHandler.ts var handleWebViewRequest = (target, handler) => { const handleMessage = (event) => __async(void 0, null, function* () { const response = yield handler(event.data); target.postMessage(response, "*"); }); window.addEventListener("message", handleMessage); return () => { window.removeEventListener("message", handleMessage); }; }; // src/utils/index.ts var generateAlphaNumericUniqueId = () => { const randomNumber = Math.floor(Math.random() * 36); const timestamp = Date.now(); const uniqueId = `${randomNumber}-${timestamp}`; const alphaNumericUniqueId = uniqueId.replace(/[\W_]/g, ""); return alphaNumericUniqueId; }; // src/RequestManager/RequestManager.ts var RequestManager = class { constructor() { /** * Send a strongly typed async postMessage request. * * @param functionName The name of the function to call * @param args The arguments to pass to the function * @param options Options for the request. Defaults to a timeout of 10 seconds. If `0` is passed * as the timeout, the request will not timeout. * @returns A promise that resolves with the return value of the function */ this.send = (functionName, args, options) => { const uid = generateAlphaNumericUniqueId(); const promise = new Promise( (resolve, reject) => { var _a; this.callbacks.set(uid, { resolve, reject }); const message = { uid, functionName, args }; this.postMessage(message); const timeout = (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : 1e4; if (timeout > 0) { setTimeout(() => { reject(new Error(`${functionName} timed out (id: ${uid})`)); this.callbacks.delete(uid); }, timeout); } } ); return promise; }; this.callbacks = /* @__PURE__ */ new Map(); } /** * Handler for postMessages to the client. * * @param message Message payload received by the webview. */ onResponse(message) { const callback = this.callbacks.get(message.uid); if (!callback) { return; } this.callbacks.delete(message.uid); if (message.error) { callback.reject(new Error(message.error)); } else { callback.resolve(message.response); } } /** * Send a strongly typed async postMessage request to the target. This should be set by the * client. * * @param _message Message payload to send to the target. */ postMessage(_message) { console.warn("[AsyncPostMessage] postMessage unimplemented"); } }; // src/WebViewRequester.ts var _WebViewRequester = class _WebViewRequester { /** * The Singleton's constructor should always be private to prevent direct * construction calls with the `new` operator. */ constructor() { /** * Execute a strongly typed promise that is executed in the parent process. */ this.execute = (functionName, args, options) => { return this.requestManager.send(functionName, args, options); }; this.requestManager = new RequestManager(); window.addEventListener( "message", (event) => { if (!event.data) { return; } this.requestManager.onResponse(event.data); } ); this.requestManager.postMessage = (message) => { window.parent.postMessage(message, "*"); }; } }; /** * The static method that controls the access to the global AsyncPostMessage instance. * * We use a singleton so that the client does not need to worry about creating multiple * instances of the `AsyncPostMessage` class. */ _WebViewRequester.getInstance = () => { if (!_WebViewRequester.instance) { _WebViewRequester.instance = new _WebViewRequester(); } return _WebViewRequester.instance; }; var WebViewRequester = _WebViewRequester; export { RequestManager, WebViewRequester, handleWebViewRequest }; //# sourceMappingURL=index.mjs.map