UNPKG

trpc-uwebsockets

Version:
97 lines (96 loc) 3.73 kB
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 {};