import { BrowserLocation } from "../transport";
export type MessageMap = {
    call: {
        id: string;
        args: any[];
        target?: BrowserLocation;
    };
    result: {
        id: string;
        result: any;
        target?: BrowserLocation;
    };
    error: {
        id: string;
        error: string;
        target?: BrowserLocation;
    };
    release: {
        id: string;
        target?: BrowserLocation;
    };
};
export interface MessageEndpoint {
    postMessage(message: [number, RPCMessage], transferables?: Transferable[]): void;
    addEventListener(event: "message", listener: (event: MessageEvent<[number, RPCMessage]>) => void): void;
    removeEventListener(event: "message", listener: (event: MessageEvent<[number, RPCMessage]>) => void): void;
    terminate?(): void;
    context?: {
        isServiceWorker: boolean;
        agentInfo?: any;
    };
}
export type RemoteCallable<T> = {
    [K in keyof T]: RemoteCallableField<T[K]>;
};
type RemoteCallableField<T> = T extends (...args: infer Args) => infer TypeReturned ? (...args: Args) => AlwaysAsync<TypeReturned> : never;
export type MaybePromise<T> = T extends Promise<any> ? T : T | Promise<T>;
type AlwaysAsync<T> = T extends Promise<any> ? T : T extends infer U | Promise<infer U> ? Promise<U> : T extends (...args: infer Args) => infer TypeReturned ? (...args: Args) => AlwaysAsync<TypeReturned> : T extends (infer ArrayElement)[] ? AlwaysAsync<ArrayElement>[] : T extends ReadonlyArray<infer ArrayElement> ? ReadonlyArray<AlwaysAsync<ArrayElement>> : T extends object ? {
    [K in keyof T]: AlwaysAsync<T[K]>;
} : T;
export type SafeRpcArgument<T> = T extends (...args: infer Args) => infer TypeReturned ? TypeReturned extends Promise<any> ? (...args: Args) => TypeReturned : (...args: Args) => TypeReturned | Promise<TypeReturned> : T extends (infer ArrayElement)[] ? SafeRpcArgument<ArrayElement>[] : T extends ReadonlyArray<infer ArrayElement> ? ReadonlyArray<SafeRpcArgument<ArrayElement>> : T extends object ? {
    [K in keyof T]: SafeRpcArgument<T[K]>;
} : T;
export declare const RETAIN_METHOD: unique symbol;
export declare const RELEASE_METHOD: unique symbol;
export declare const RETAINED_BY: unique symbol;
export interface Retainer {
    add(manageable: MemoryManageable): void;
}
export interface MemoryManageable {
    readonly [RETAINED_BY]: Set<Retainer>;
    [RETAIN_METHOD](): void;
    [RELEASE_METHOD](): void;
}
export interface EncodingStrategy {
    encode(value: unknown): [any, Transferable[]?];
    decode(value: unknown, retainedBy?: Iterable<Retainer>): unknown;
    call(id: string, args: any[]): Promise<any>;
    release(id: string): void;
    terminate?(): void;
}
export interface EncodingStrategyApi {
    uuid(): string;
    release(id: string): void;
    call(id: string, args: any[], retainedBy?: Iterable<Retainer>): Promise<any>;
}
export type CallMessage = {
    call: {
        id: string;
        args: any[];
        target?: BrowserLocation;
    };
};
export type ResultMessage = {
    result: {
        id: string;
        result: any;
        target?: BrowserLocation;
    };
};
export type ErrorMessage = {
    error: {
        id: string;
        error: string;
        target?: BrowserLocation;
    };
};
export type ReleaseMessage = {
    release: {
        id: string;
        target?: BrowserLocation;
    };
};
export type RPCMessage = CallMessage | ResultMessage | ErrorMessage | ReleaseMessage;
export {};
