{"version":3,"sources":["../src/ParentHandler.ts","../src/RequestManager/RequestManager.ts","../src/WebViewRequester.ts"],"sourcesContent":["import {\n  AsyncPostMessageRequest,\n  AsyncPostMessageResponse,\n  Promises,\n} from \"./RequestManager/types\";\n\n/**\n * Type for unsubscribing from an event listener.\n */\ntype Unsubscribe = () => void;\n\n/**\n * Handles a requests from the webview using the given callback. This code should be run on the\n * parent context.\n *\n * @param {object} target - The target object that has a postMessage method (ie. iframe).\n * @param {function} handler - The handler function that takes an AsyncPostMessageRequest and\n * returns a Promise of AsyncPostMessageResponse.\n * @return {function} - The unsubscribe function that removes the event listener. Useful for React.\n */\nexport const handleWebViewRequest = <PromisesInterface extends Promises>(\n  target: { postMessage: typeof window.postMessage },\n  handler: (\n    request: AsyncPostMessageRequest<PromisesInterface>\n  ) => Promise<AsyncPostMessageResponse<PromisesInterface>>\n): Unsubscribe => {\n  const handleMessage = async (\n    event: MessageEvent<AsyncPostMessageRequest<PromisesInterface>>\n  ) => {\n    // Execute the business logic.\n    const response = await handler(event.data);\n\n    // Send the response back to the iFrame so it can resolve.\n    target.postMessage(response, \"*\");\n  };\n\n  window.addEventListener(\"message\", handleMessage);\n\n  return () => {\n    window.removeEventListener(\"message\", handleMessage);\n  };\n};\n","import { v4 as uuidv4 } from \"uuid\";\nimport { AsyncPostMessageRequest, AsyncPostMessageResponse, CallbackType, Promises, UidType } from \"./types\";\n\n/**\n * A class for managing async postMessage requests and their promise wrappers. Each instance\n * stores a map of callbacks for each unique ID. It does not wrap the `postMessage` API. Instead,\n * it allows the client to set the listener and postMessage methods on their own.\n */\nexport class RequestManager<PromisesInterface extends Promises> {\n  /**\n   * Map of callbacks for each promise's unique ID.\n   */\n  private callbacks: Map<UidType, CallbackType>;\n\n  constructor() {\n    this.callbacks = new Map();\n  }\n\n  /**\n   * Send a strongly typed async postMessage request.\n   *\n   * @param functionName The name of the function to call\n   * @param args The arguments to pass to the function\n   * @param options Options for the request. Defaults to a timeout of 10 seconds. If `0` is passed\n   * as the timeout, the request will not timeout.\n   * @returns A promise that resolves with the return value of the function\n   */\n  public send = <FnNameType extends keyof PromisesInterface & string>(\n    functionName: FnNameType,\n    args: Parameters<PromisesInterface[FnNameType]>,\n    options?: { timeoutMs: number }\n  ): Promise<ReturnType<PromisesInterface[FnNameType]>> => {\n    // Generate a unique ID for this request.\n    const uid = uuidv4();\n\n    const promise = new Promise<ReturnType<PromisesInterface[FnNameType]>>((resolve, reject) => {\n      this.callbacks.set(uid, { resolve, reject });\n      const message: AsyncPostMessageRequest<PromisesInterface> = {\n        uid,\n        functionName,\n        args,\n      };\n      this.postMessage(message);\n\n      // Set a timeout for the request (defaults to 10 seconds).\n      const timeout = options?.timeoutMs ?? 10000;\n      if (timeout > 0) {\n        setTimeout(() => {\n          reject(new Error(`${functionName} timed out (id: ${uid})`));\n          this.callbacks.delete(uid);\n        }, timeout);\n      }\n    });\n\n    return promise;\n  };\n\n  /**\n   * Handler for postMessages to the client.\n   *\n   * @param message Message payload received by the webview.\n   */\n  public onResponse(message: AsyncPostMessageResponse<PromisesInterface>): void {\n    const callback = this.callbacks.get(message.uid);\n\n    // If the callback is not defined, do nothing as it means the request timed out.\n    if (!callback) {\n      return;\n    }\n\n    this.callbacks.delete(message.uid);\n    if (message.error) {\n      callback.reject(new Error(message.error));\n    } else {\n      callback.resolve(message.response);\n    }\n  }\n\n  /**\n   * Send a strongly typed async postMessage request to the target. This should be set by the\n   * client.\n   *\n   * @param _message Message payload to send to the target.\n   */\n  public postMessage(_message: AsyncPostMessageRequest<PromisesInterface>): void {\n    console.warn(\"[AsyncPostMessage] postMessage unimplemented\");\n  }\n}\n","import { RequestManager } from \"./RequestManager/RequestManager\";\nimport { AsyncPostMessageResponse, Promises } from \"./RequestManager/types\";\n\n/**\n * The Singleton class defines the `getInstance` method that lets clients access\n * the unique singleton instance.\n */\nexport class WebViewRequester<PromisesInterface extends Promises = any> {\n  private static instance: WebViewRequester;\n\n  private requestManager: RequestManager<PromisesInterface>;\n\n  /**\n   * The Singleton's constructor should always be private to prevent direct\n   * construction calls with the `new` operator.\n   */\n  private constructor() {\n    // Setup instance of RequestManager that will be used by all calls.\n    this.requestManager = new RequestManager();\n\n    // Listen for messages from the parent.\n    window.addEventListener(\n      \"message\",\n      (event: MessageEvent<AsyncPostMessageResponse<PromisesInterface>>) => {\n        if (!event.data) {\n          return;\n        }\n        this.requestManager.onResponse(event.data);\n      }\n    );\n\n    // Setup data pipeline to send messages to the parent.\n    this.requestManager.postMessage = (message) => {\n      window.parent.postMessage(message, \"*\");\n    };\n  }\n\n  /**\n   * The static method that controls the access to the global AsyncPostMessage instance.\n   *\n   * We use a singleton so that the client does not need to worry about creating multiple\n   * instances of the `AsyncPostMessage` class.\n   */\n  public static getInstance = <\n    PromisesInterface extends Promises\n  >(): WebViewRequester<PromisesInterface> => {\n    if (!WebViewRequester.instance) {\n      WebViewRequester.instance = new WebViewRequester();\n    }\n\n    return WebViewRequester.instance;\n  };\n\n  /**\n   * Execute a strongly typed promise that is executed in the parent process.\n   */\n  public execute = <FnNameType extends keyof PromisesInterface & string>(\n    functionName: FnNameType,\n    args: Parameters<PromisesInterface[FnNameType]>,\n    options?: { timeoutMs: number }\n  ): Promise<ReturnType<PromisesInterface[FnNameType]>> => {\n    return this.requestManager.send(functionName, args, options);\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoBO,IAAM,uBAAuB,CAClC,QACA,YAGgB;AAChB,QAAM,gBAAgB,CACpB,UACG;AAEH,UAAM,WAAW,MAAM,QAAQ,MAAM,IAAI;AAGzC,WAAO,YAAY,UAAU,GAAG;AAAA,EAClC;AAEA,SAAO,iBAAiB,WAAW,aAAa;AAEhD,SAAO,MAAM;AACX,WAAO,oBAAoB,WAAW,aAAa;AAAA,EACrD;AACF;;;ACzCA,SAAS,MAAM,cAAc;AAQtB,IAAM,iBAAN,MAAyD;AAAA,EAM9D,cAAc;AAad;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAO,OAAO,CACZ,cACA,MACA,YACuD;AAEvD,YAAM,MAAM,OAAO;AAEnB,YAAM,UAAU,IAAI,QAAmD,CAAC,SAAS,WAAW;AAnChG;AAoCM,aAAK,UAAU,IAAI,KAAK,EAAE,SAAS,OAAO,CAAC;AAC3C,cAAM,UAAsD;AAAA,UAC1D;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,aAAK,YAAY,OAAO;AAGxB,cAAM,WAAU,wCAAS,cAAT,YAAsB;AACtC,YAAI,UAAU,GAAG;AACf,qBAAW,MAAM;AACf,mBAAO,IAAI,MAAM,GAAG,YAAY,mBAAmB,GAAG,GAAG,CAAC;AAC1D,iBAAK,UAAU,OAAO,GAAG;AAAA,UAC3B,GAAG,OAAO;AAAA,QACZ;AAAA,MACF,CAAC;AAED,aAAO;AAAA,IACT;AAxCE,SAAK,YAAY,oBAAI,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8CO,WAAW,SAA4D;AAC5E,UAAM,WAAW,KAAK,UAAU,IAAI,QAAQ,GAAG;AAG/C,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,SAAK,UAAU,OAAO,QAAQ,GAAG;AACjC,QAAI,QAAQ,OAAO;AACjB,eAAS,OAAO,IAAI,MAAM,QAAQ,KAAK,CAAC;AAAA,IAC1C,OAAO;AACL,eAAS,QAAQ,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,YAAY,UAA4D;AAC7E,YAAQ,KAAK,8CAA8C;AAAA,EAC7D;AACF;;;AChFO,IAAM,oBAAN,MAAM,kBAA2D;AAAA;AAAA;AAAA;AAAA;AAAA,EAS9D,cAAc;AAwCtB;AAAA;AAAA;AAAA,SAAO,UAAU,CACf,cACA,MACA,YACuD;AACvD,aAAO,KAAK,eAAe,KAAK,cAAc,MAAM,OAAO;AAAA,IAC7D;AA5CE,SAAK,iBAAiB,IAAI,eAAe;AAGzC,WAAO;AAAA,MACL;AAAA,MACA,CAAC,UAAqE;AACpE,YAAI,CAAC,MAAM,MAAM;AACf;AAAA,QACF;AACA,aAAK,eAAe,WAAW,MAAM,IAAI;AAAA,MAC3C;AAAA,IACF;AAGA,SAAK,eAAe,cAAc,CAAC,YAAY;AAC7C,aAAO,OAAO,YAAY,SAAS,GAAG;AAAA,IACxC;AAAA,EACF;AA4BF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAxDa,kBAoCG,cAAc,MAEgB;AAC1C,MAAI,CAAC,kBAAiB,UAAU;AAC9B,sBAAiB,WAAW,IAAI,kBAAiB;AAAA,EACnD;AAEA,SAAO,kBAAiB;AAC1B;AA5CK,IAAM,mBAAN;","names":[]}