import type { EventHandler, RequestHandler, SubscribeHandler } from "./types.js";
/**
 * Structured error that can be used for errors on requests,
 * such as data validation errors.
 *
 * A handler can throw this error and it will properly be serialized
 * as part of the reply and deserialized on the other side. This allows
 * to return errors with additional context as a low-level primitive.
 */
export declare class RequestError extends Error {
    type: string;
    data: unknown;
    constructor(message: string, type: string, data: unknown, options?: {
        cause?: unknown;
    });
}
declare const messageTypeRequest = "IFRAME-MESSAGE-REQUEST";
declare const messageTypeResponse = "IFRAME-MESSAGE-RESPONSE";
declare const messageTypeEvent = "IFRAME-MESSAGE-EVENT";
/**
 * @hidden
 * @internal
 */
export type IframeMessageEvent = {
    type: typeof messageTypeEvent;
    action: string;
    payload: unknown;
};
/**
 * @hidden
 * @internal
 */
export type IframeMessageRequest = {
    /**
     * The ID is a unique identifier used to connect
     * the response message to the proper request.
     */
    id: string;
    type: typeof messageTypeRequest;
    action: string;
    payload: unknown;
};
/**
 * @hidden
 * @internal
 */
export type IframeMessageResponse = {
    /**
     * The ID is a unique identifier used to connect
     * the response message to the proper request.
     */
    id: string;
    type: typeof messageTypeResponse;
    payload: unknown;
    error?: boolean | undefined;
};
/**
 * @hidden
 * @internal
 */
export type CreateSubscriptionResult = {
    unsubscribe: () => void;
};
/**
 * @hidden
 * @internal
 */
export type IframeMessengerOptions = {
    source: Window;
    /**
     * The origin where messages are expected from and that we will
     * use as destination for outgoing messages.
     *
     * Set to undefined if not checking origin in incoming messages
     * and sending outgoing messages to "*".
     *
     * Do not use undefined in the configuration side of an iframe if
     * sending sensitive data such as credentials.
     */
    sourceOrigin?: string | undefined;
    requestResolver?: ((action: string) => RequestHandler | undefined) | undefined;
    eventResolver?: ((action: string) => EventHandler | undefined) | undefined;
    subscribeResolver?: ((name: string) => SubscribeHandler | undefined) | undefined;
    debug?: boolean | undefined;
    /**
     * A function that optionally returns a function that can be used to
     * intercept incoming postMessage messages, before they are passed
     * to the relevant handlers. This can be used to transform the incoming data.
     */
    incomingMessageInterceptorResolver?: (() => ((message: unknown) => unknown) | undefined) | undefined;
    /**
     * A function that optionally returns a function that can be used to
     * intercept outgoing postMessage messages, before they are sent using
     * postMessage. This can be used to transform the outgoing data.
     */
    outgoingMessageInterceptorResolver?: (() => ((message: unknown, options: {
        request?: IframeMessageRequest | undefined;
    }) => unknown) | undefined) | undefined;
};
type DeregisterFn = () => void;
/**
 * IframeMessenger handles communication in/out of an iframe.
 *
 * It creates an abstraction on top of the Window.postMessage() browser
 * API to make it more convenient to handle states, message passing
 * and routing messages to handlers.
 *
 * Functionality provided:
 *
 * - Sending requests and waiting for the response for it. Think of it
 *   as a way of doing async functions across browser windows. Since the
 *   cross-window communcation is async itself, there is no support for
 *   synchronous requests.
 *
 * - Sending events to the other window. Events are one-way messages that
 *   do not expect a reply. Use cases for this is rare, and in most
 *   cases solved by subscriptions instead.
 *
 * - Subscriptions. This is a way to subscribe to specific events from the
 *   other window. The window that exposes a subscription source will contain
 *   a handler that can emit events for it when the subscription is created.
 *   This allows for lazy event streams that are only created when needed.
 *
 *   Internally subscriptions are built on top of both requests (creating and
 *   deleting subscriptions) and events mentioned above.
 *
 *   Subscriptions are unsubscribed automatically on disconnect.
 *
 * - Connected callbacks. This allows to add logic that should happen
 *   as soon as the connection between the windows are established.
 *
 * By default messages are queued until the connection is established,
 * so the user does not have to be concerned about connection details.
 *
 * When an iframe is removed from DOM, the connection should be explicitly
 * disconnected by calling disconnect() to trigger proper cleanup.
 *
 * @hidden
 * @internal
 */
export declare class IframeMessenger {
    #private;
    debug: boolean;
    source: Window;
    sourceOrigin: string | undefined;
    incomingMessageInterceptorResolver: (() => ((message: unknown) => unknown) | undefined) | undefined;
    outgoingMessageInterceptorResolver: (() => ((message: unknown, options: {
        request?: IframeMessageRequest | undefined;
    }) => unknown) | undefined) | undefined;
    requestResolver: ((action: string) => RequestHandler | undefined) | undefined;
    eventResolver: ((action: string) => EventHandler | undefined) | undefined;
    subscribeResolver: ((name: string) => SubscribeHandler | undefined) | undefined;
    constructor(options: IframeMessengerOptions);
    connect(): void;
    disconnect(): void;
    /**
     * Subscribe to state transitions for being connected and
     * from being connected to disconnected.
     *
     * This essentially acts as a boolean flag if it is connected
     * or not.
     */
    onStateChange(handler: (state: "connected" | "disconnected") => void): DeregisterFn;
    get isConnected(): boolean;
    /**
     * Wait for the state to be connected.
     *
     * If a disconnect (e.g. due to unmount) is requested before being
     * connected, the promise will be rejected to ensure the promise
     * is fulfilled.
     */
    connectedPromise(): Promise<void>;
    sendRequest<R>(action: string): Promise<R>;
    sendRequest<T, R>(action: string, payload: T, transfer?: Transferable[]): Promise<R>;
    sendEvent(action: string): Promise<void>;
    sendEvent<T>(action: string, payload: T, transfer?: Transferable[]): Promise<void>;
    createSubscription<T, O extends Record<string, unknown> = Record<string, unknown>>(name: string, handler: (event: T) => void, options?: O): Promise<CreateSubscriptionResult>;
}
export {};
