/** * `IframeChannel` — the postMessage channel for the iframe topology * (host-app + iframe mini-apps). * * One class serves both ends: * - **Client-side** (inside the mini-app iframe): `getTarget` returns * `window.parent`. * - **Host-side, fixed** (one per known mini-app iframe): `getTarget` returns * that iframe's `contentWindow`, `filterBySource` is on, and an `instanceId` * is supplied — so N iframes never cross-talk. * - **Host-side, auto-bind** (`autoBind: true`): no target is known up front; * the channel binds its target to `event.source` of the first inbound Apna * message (the mini-app's handshake) and thereafter only accepts messages * from that source. This is what the legacy single-`ApnaHost` path uses. * * Every instance attaches and detaches its own `message` listener; there is no * shared/static state, so many channels can coexist. */ import { ApnaMessage } from '../protocol'; import { Channel } from './index'; export interface IframeChannelOptions { /** * Resolves the window to post messages TO. Client-side: * `() => window.parent`. Host-side (fixed): `() => iframe.contentWindow`. * Optional when `autoBind` is set — the target is then learned from the * first inbound message. */ getTarget?: () => Window | null; /** * Host-side: bind the target to `event.source` of the first inbound Apna * message and filter all later inbound messages to that source. */ autoBind?: boolean; /** Window to listen on for inbound `message` events. Default: `window`. */ listenOn?: Window; /** * Expected peer origin for validation. Default `'*'` (no origin check) — * production callers should pass the real origin. */ targetOrigin?: string; /** * Host-side isolation: only accept inbound messages whose `event.source` is * the target window. Leave off client-side (the only peer is the parent). * Implied once `autoBind` has bound a target. */ filterBySource?: boolean; /** * Only accept inbound messages carrying this `instanceId` — host-side * parallel-iframe isolation. Host-inbound messages all carry an `instanceId`. */ instanceId?: string; } export declare class IframeChannel implements Channel { private readonly getTargetOpt?; private readonly autoBind; private readonly listenOn; private readonly targetOrigin; private readonly filterBySource; private readonly instanceId?; private readonly handlers; private boundTarget; private listening; private disposed; constructor(options: IframeChannelOptions); /** The currently bound target (after auto-bind), if any. */ get target(): Window | null; send(message: ApnaMessage): void; onMessage(handler: (message: ApnaMessage) => void): () => void; /** Resolves once the target window is available. */ ready(): Promise; dispose(): void; private resolveTarget; private readonly onWindowMessage; private ensureListening; private stopListening; }