{"version":3,"sources":["../src/logger.ts","../src/index.ts"],"sourcesContent":["export const logger = {\r\n  log: (...args: any[]) => {\r\n    console.log(...args)\r\n  },\r\n  error: (...args: any[]) => {\r\n    console.error(...args)\r\n  }\r\n}","import { logger } from \"./logger\"\r\n\r\ntype ChannelMsg<T> = {\r\n  success: boolean\r\n  channel: string\r\n  isSetup?: boolean\r\n  data: T\r\n  error?: { msg: string; stack: string }\r\n}\r\n\r\ntype CreateChannelReturn<Req, Res> = {\r\n  request: (message: Req, windowObj: Window) => Promise<Res>\r\n  handle: (callback: (req: Req) => Promise<Res>) => void\r\n}\r\n\r\n/**\r\n * Create a channel to communicate with the window.\r\n * @param channel - The channel to create.\r\n * @returns The request and handle functions.\r\n */\r\nexport const createChannel = <Req, Res>(\r\n  channel: string\r\n): CreateChannelReturn<Req, Res> => {\r\n  const requestChannel = `request:/${channel}`\r\n  const responseChannel = `response:/${channel}`\r\n\r\n  // 2. Handle logic.\r\n  // 2.1 Check if the channel is setup.\r\n  let isSetup = false\r\n\r\n  // 2.1 Access the setup message from child window.\r\n  const processSetupMsg = () =>\r\n    new Promise<void>((resolve) => {\r\n      const onMessage = (event: MessageEvent) => {\r\n        // 1. Handle logic.\r\n        if (event.origin !== window.location.origin) {\r\n          return\r\n        }\r\n\r\n        const channelMsg = event.data as ChannelMsg<Req>\r\n        if (channelMsg.channel !== requestChannel) {\r\n          return\r\n        }\r\n        if (channelMsg.isSetup) {\r\n          isSetup = true\r\n          window.removeEventListener(\"message\", onMessage)\r\n          resolve()\r\n          logger.log(`[windows message: request side]: setup success`)\r\n          return\r\n        }\r\n      }\r\n      window.addEventListener(\"message\", onMessage)\r\n    })\r\n\r\n  processSetupMsg()\r\n\r\n  const waitChildWindowSetup = async () => {\r\n    // 2. Handle logic.\r\n    if (isSetup) {\r\n      return\r\n    }\r\n    await processSetupMsg()\r\n  }\r\n\r\n  // 3. Return the result.\r\n  return {\r\n    request: (message: Req, windowObj: Window = window) =>\r\n      request(\r\n        message,\r\n        windowObj,\r\n        responseChannel,\r\n        requestChannel,\r\n        waitChildWindowSetup\r\n      ),\r\n\r\n    handle: (callback: (req: Req) => Promise<Res>) =>\r\n      handle(callback, requestChannel, responseChannel)\r\n  }\r\n}\r\n\r\n/**\r\n * Handle the request from the window.\r\n * @param callback - The callback to handle the request.\r\n */\r\nconst handle = <Req, Res>(\r\n  callback: (req: Req) => Promise<Res>,\r\n  requestChannel: string,\r\n  responseChannel: string\r\n) => {\r\n  // 2. Handle logic.\r\n  // 2.1 Send setup message to parent window.\r\n  const setupMsg: ChannelMsg<Req> = {\r\n    channel: requestChannel,\r\n    success: true,\r\n    isSetup: true,\r\n    data: undefined as unknown as Req\r\n  }\r\n  window.parent.postMessage(setupMsg)\r\n  logger.log(\r\n    `[windows message: handle side]: setup: ${JSON.stringify(setupMsg)}`\r\n  )\r\n\r\n  const messageHandler = (event: MessageEvent) => {\r\n    // 1. Handle logic.\r\n    if (event.origin !== window.location.origin) {\r\n      return\r\n    }\r\n\r\n    const channelMsg = event.data as ChannelMsg<Req>\r\n    if (channelMsg.channel !== requestChannel) {\r\n      return\r\n    }\r\n    \r\n    // Skip setup messages - they are not actual requests\r\n    if (channelMsg.isSetup) {\r\n      return\r\n    }\r\n    \r\n    logger.log(\r\n      `[windows message: handle side]: Receive ${JSON.stringify(channelMsg)} `\r\n    )\r\n\r\n    // 2. Handle logic.\r\n    callback(channelMsg.data)\r\n      .then((res) => {\r\n        const msg: ChannelMsg<Res> = {\r\n          channel: responseChannel,\r\n          success: true,\r\n          data: res\r\n        }\r\n\r\n        event.source?.postMessage(msg, { targetOrigin: event.origin })\r\n\r\n        logger.log(\r\n          `[windows message: handle side]: Post ${JSON.stringify(msg)} `\r\n        )\r\n      })\r\n      .catch((err) => {\r\n        const errMsg: ChannelMsg<Res> = {\r\n          channel: responseChannel,\r\n          success: false,\r\n          data: undefined as unknown as Res,\r\n          error: {\r\n            msg: err.message,\r\n            stack: err.stack || \"\"\r\n          }\r\n        }\r\n        event.source?.postMessage(errMsg, { targetOrigin: event.origin })\r\n        logger.error(\r\n          `[windows message: handle side]: Post ${JSON.stringify(errMsg)} `\r\n        )\r\n      })\r\n      // Keep the handler active for multiple requests - don't remove listener\r\n  }\r\n\r\n  // 2.2 Listen to message from parent window.\r\n  window.addEventListener(\"message\", messageHandler)\r\n}\r\n\r\n/**\r\n * Request the message to the window.\r\n * @param message - The message to request.\r\n * @returns The response from the window.\r\n */\r\nconst request = async <Req, Res>(\r\n  message: Req,\r\n  windowObj: Window = window,\r\n  responseChannel: string,\r\n  requestChannel: string,\r\n  waitChildWindowSetup: () => Promise<void>\r\n): Promise<Res> => {\r\n  // 2. Handle logic.\r\n  await waitChildWindowSetup()\r\n\r\n  // 2.2 Send message to child window.\r\n  return new Promise<Res>((resolve, reject) => {\r\n    const messageHandler = (event: MessageEvent) => {\r\n      // 1. Handle input.\r\n      if (event.origin !== window.location.origin) {\r\n        return\r\n      }\r\n      // 1.2 If the channel is not the same, return.\r\n      const channelMsg = event.data as ChannelMsg<Res>\r\n      if (channelMsg.channel !== responseChannel) {\r\n        return\r\n      }\r\n\r\n      // 2. Handle logic.\r\n      logger.log(\r\n        `[windows message: request side]: Receive ${JSON.stringify(channelMsg)} `\r\n      )\r\n      if (channelMsg.success) {\r\n        resolve(channelMsg.data)\r\n      } else {\r\n        reject(channelMsg.error?.msg || \"Unknown error\")\r\n        console.error(channelMsg.error?.msg)\r\n        console.error(channelMsg.error?.stack)\r\n      }\r\n\r\n      // 3. Remove the listener.\r\n      window.removeEventListener(\"message\", messageHandler)\r\n    }\r\n\r\n    window.addEventListener(\"message\", messageHandler)\r\n\r\n    const msg: ChannelMsg<Req> = {\r\n      channel: requestChannel,\r\n      success: true,\r\n      data: message\r\n    }\r\n\r\n    logger.log(`[windows message: request side]: Post ${JSON.stringify(msg)} `)\r\n    windowObj.postMessage(msg, \"*\")\r\n  })\r\n}\r\n"],"mappings":"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","names":[]}