{"version":3,"sources":["../src/iframe/agent/has-storage-access.ts","../src/iframe/agent/path.ts","../src/iframe/agent/tunnel.ts","../../common/src/directories.ts","../src/common/port.ts","../src/iframe/agent/websocket.ts","../src/iframe/agent/message.ts","../src/iframe/agent/main.ts"],"sourcesContent":["export async function hasStorageAccess() {\n  if (!document.requestStorageAccess) {\n    return true;\n  }\n\n  if (await document.hasStorageAccess()) {\n    return true;\n  }\n\n  try {\n    const permission = await navigator.permissions.query({\n      name: 'storage-access' as PermissionName,\n    });\n    if (!permission) return false;\n    if (permission.state === 'granted') {\n      try {\n        await document.requestStorageAccess();\n        return true;\n      } catch (error) {\n        return false;\n      }\n    }\n  } catch (err) {\n    console.error('failed to check storage access:', err);\n  }\n  return false;\n}\n","const url =\n  typeof window !== 'undefined' ? new URL(window.location.href) : undefined;\nconst paths = url?.pathname.split('/');\n\nexport const appId = paths?.[paths.length - 2];\n","import type { IframeTunnelRequest } from '@/common/interop/iframe';\nimport type { TunnelResponse } from '@/common/interop/tunnel';\n\nimport { appId } from './path';\n\nexport async function tunnel({\n  instanceId,\n  instanceTitle,\n  instanceUrl,\n}: IframeTunnelRequest): Promise<TunnelResponse | undefined> {\n  const tunnelUrl = `/api/tunnel/${appId}?title=${encodeURIComponent(\n    instanceTitle || '',\n  )}&src=${encodeURIComponent(\n    instanceUrl || '',\n  )}&instanceId=${encodeURIComponent(instanceId || '')}`;\n  try {\n    const res = await fetch(tunnelUrl);\n    return res.json();\n  } catch (err) {\n    console.error('failed to call tunnel:', err);\n  }\n}\n","/**\n * Parameter name for directory identifier.\n * Directories can contain a collection of apps.\n */\nexport const directoryParamName = 'subDirectory';\n\n/**\n * Parameter name for namespace identifier.\n * Namespaces can contain a collection of directories, intents and contexts.\n */\nexport const namespaceParamName = 'directory';\n","export const portTimeoutError = new Error(\n  'timed out waiting for iframe message',\n);\n\nexport function isPortTimeoutError(err: unknown) {\n  return portTimeoutError === err;\n}\n\nexport function waitForPortMessage<TMessage extends { topic: string }>(\n  port: MessagePort,\n  topics: Array<TMessage['topic']>,\n  timeoutMs: number = 15000,\n) {\n  const topicsSet = new Set(topics);\n  return new Promise<TMessage>((res, rej) => {\n    const timeout =\n      timeoutMs > 0\n        ? window.setTimeout(() => {\n            port.removeEventListener('message', listener);\n            rej(portTimeoutError);\n          }, timeoutMs)\n        : undefined;\n    const listener = (event: MessageEvent) => {\n      try {\n        const response: TMessage = JSON.parse(event.data);\n        if (!topicsSet.has(response.topic)) return;\n        res(response);\n        clearTimeout(timeout);\n        port.removeEventListener('message', listener);\n      } catch (err) {\n        // ignored\n      }\n    };\n    port.addEventListener('message', listener);\n  });\n}\n\nexport function postMessageToPort<TMessage extends { topic: string }>(\n  port: MessagePort,\n  message?: TMessage,\n) {\n  if (!message) return;\n  port.postMessage(JSON.stringify(message));\n}\n","import type {\n  IframeCloseResponse,\n  IframeConnectRequest,\n  IframeErrorResponse,\n  IframeMessageResponse,\n  IframeOpenResponse,\n} from '@/common/interop/iframe';\nimport { directoryParamName, namespaceParamName } from '@/common/directories';\nimport { postMessageToPort } from '../../common/port';\n\nexport function createWebSocket(\n  port: MessagePort,\n  { directory, namespace, instanceId }: IframeConnectRequest,\n) {\n  const path = `/interop/?instanceId=${instanceId}&${directoryParamName}=${directory}&${namespaceParamName}=${namespace}`;\n  const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';\n  const host = window.location.host;\n  const url = `${protocol}${host}${path}`;\n\n  const ws = new WebSocket(url);\n  ws.onopen = () =>\n    postMessageToPort<IframeOpenResponse>(port, { topic: 'open' });\n  ws.onmessage = ({ data }) =>\n    postMessageToPort<IframeMessageResponse>(port, { topic: 'message', data });\n  ws.onerror = () =>\n    postMessageToPort<IframeErrorResponse>(port, { topic: 'error' });\n  ws.onclose = ({ code }) =>\n    postMessageToPort<IframeCloseResponse>(port, {\n      topic: 'close',\n      code,\n      directory,\n      namespace,\n      instanceId,\n    });\n  return ws;\n}\n","import type {\n  IframeHandshakeResponse,\n  IframeHasStorageAccessResponse,\n  IframeRequest,\n} from '@/common/interop/iframe';\n\nimport { hasStorageAccess } from './has-storage-access';\nimport { tunnel } from './tunnel';\nimport { createWebSocket } from './websocket';\nimport { postMessageToPort } from '../../common/port';\n\nexport function createHandlePortMessage() {\n  let ws: WebSocket | undefined;\n\n  return async function handlePortMessage(\n    port: MessagePort,\n    { data }: MessageEvent,\n  ) {\n    const request: IframeRequest = JSON.parse(data);\n\n    switch (request.topic) {\n      case 'connect':\n        ws?.close();\n        ws = createWebSocket(port, request);\n        break;\n      case 'send':\n        ws?.send(JSON.stringify({ action: 'send', message: request.message }));\n        break;\n      case 'close':\n        ws?.close();\n        break;\n      case 'has-storage-access':\n        postMessageToPort<IframeHasStorageAccessResponse>(port, {\n          topic: 'has-storage-access',\n          hasStorageAccess: await hasStorageAccess(),\n        });\n        break;\n      case 'tunnel':\n        postMessageToPort(port, await tunnel(request));\n        break;\n    }\n  };\n}\n\nconst handlePortMessage = createHandlePortMessage();\nexport function handleWindowMessage({ ports }: MessageEvent) {\n  if (!ports.length) return;\n\n  window.removeEventListener('message', handleWindowMessage);\n\n  const port = ports[0];\n  port.addEventListener('message', handlePortMessage.bind(undefined, port));\n  port.start();\n\n  postMessageToPort<IframeHandshakeResponse>(port, { topic: 'handshake' });\n}\n","import { handleWindowMessage } from './message';\n\nwindow.addEventListener('message', handleWindowMessage);\n"],"mappings":"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","names":["hasStorageAccess","permission","err","url","paths","appId","tunnel","instanceId","instanceTitle","instanceUrl","tunnelUrl","appId","err","directoryParamName","namespaceParamName","portTimeoutError","postMessageToPort","port","message","createWebSocket","port","directory","namespace","instanceId","path","directoryParamName","namespaceParamName","protocol","host","url","ws","postMessageToPort","data","code","createHandlePortMessage","ws","port","data","request","createWebSocket","postMessageToPort","hasStorageAccess","tunnel","handlePortMessage","handleWindowMessage","ports","handleWindowMessage"]}