import { type AnyRouter, type CreateContextCallback, inferRouterContext } from '@trpc/server';
import { NodeHTTPCreateContextFnOptions } from '@trpc/server/adapters/node-http';
import { type BaseHandlerOptions } from '@trpc/server/http';
import { type MaybePromise } from '@trpc/server/unstable-core-do-not-import';
import { URL } from 'url';
import type { TemplatedApp, WebSocket, WebSocketBehavior } from 'uWebSockets.js';
import { HttpResponseDecorated } from './fetchCompat';
type RemoveFunctions<T> = {
    [K in keyof T as NonNullable<T[K]> extends Function ? never : K]: T[K];
};
/**
 * A structure holding settings for a WebSocket handler.
 */
export type WebSocketBehaviorOptions = RemoveFunctions<WebSocketBehavior<any>>;
export type WebSocketConnection = WebSocket<WebsocketData>;
/**
 * @public
 */
export type CreateWSSContextFnOptions = NodeHTTPCreateContextFnOptions<Request, HttpResponseDecorated> & {
    client: WebSocketConnection;
};
export type CreateWSSContextFn<TRouter extends AnyRouter> = (opts: CreateWSSContextFnOptions) => MaybePromise<inferRouterContext<TRouter>>;
export type WSConnectionHandlerOptions<TRouter extends AnyRouter> = BaseHandlerOptions<TRouter, Request> & CreateContextCallback<inferRouterContext<TRouter>, CreateWSSContextFn<TRouter>>;
export type WebsocketsKeepAlive = {
    /**
     * Enable heartbeat messages
     * @default false
     */
    enabled: boolean;
    /**
     * Heartbeat interval in milliseconds
     * @default 30_000
     */
    pingMs?: number | undefined;
    /**
     * Terminate the WebSocket if no pong is received after this many milliseconds
     * @default 5_000
     */
    pongWaitMs?: number | undefined;
};
/**
 * WebSockets handler definition
 */
export type WebsocketsHandlerOptions<TRouter extends AnyRouter> = WSConnectionHandlerOptions<TRouter> & {
    /**
     * Url path prefix where the tRPC server will be registered.
     * @default ''
     */
    prefix?: string | undefined;
    /**
     * Specify if SSL is used. Set to true if you are using SSLApp or if the server is served behind SSL reverse proxy.
     * @default false
     */
    ssl?: boolean | undefined;
    keepAlive?: WebsocketsKeepAlive | undefined;
    /**
     * Disable responding to ping messages from the client
     * **Not recommended** - this is mainly used for testing
     * @default false
     */
    dangerouslyDisablePong?: boolean | undefined;
    /**
     * uWebSockets.js WebSocket hander settings
     */
    uWsBehaviorOptions?: WebSocketBehaviorOptions | undefined;
};
interface Completer {
    promise: Promise<void>;
    resolve: () => void;
    reject: (error: Error) => void;
}
type WebsocketData = {
    req: Request;
    clientSubscriptions: Map<number | string, AbortController>;
    abortController: AbortController;
    ctx: inferRouterContext<AnyRouter> | undefined;
    /**
     * inside-out promise that resolves when context is ready.
     *
     * - when this is null, the context resolution will be started
     * - otherwise all requests must await context resolution
     */
    ctxCompleter: Completer | null;
    keepAlive: KeepAliver | null;
    url: URL;
};
export declare function getWSConnectionHandler<TRouter extends AnyRouter>(opts: WebsocketsHandlerOptions<TRouter>, allClients: Set<WebSocketConnection>): WebSocketBehavior<WebsocketData>;
export declare function applyWebsocketHandler<TRouter extends AnyRouter>(app: TemplatedApp, opts: WebsocketsHandlerOptions<TRouter>): {
    broadcastReconnectNotification: () => void;
};
type KeepAliver = {
    onMessage: () => void;
    onClose: () => void;
};
export declare function handleKeepAlive(client: WebSocketConnection, pingMs?: number, pongWaitMs?: number): KeepAliver;
export {};
