/** * @fileoverview WebSocket RPC server implementation for Cloudflare Durable Objects. * * This module provides functionality to set up WebSocket-based RPC communication * on Cloudflare Durable Objects with hibernation support. It handles the complete * lifecycle of WebSocket RPC servers, including message routing, protocol handling, * and automatic recovery after hibernation cycles. * * Key features: * - Hibernation-compatible WebSocket handling * - Automatic RPC server lifecycle management * - Effect-based RPC protocol implementation * - Cost optimization through hibernation support * * @see {@link https://developers.cloudflare.com/durable-objects/best-practices/websockets/ Cloudflare WebSocket Best Practices} */ import { Context, Layer, Mailbox, RpcMessage, RpcSerialization, RpcServer } from '@livestore/utils/effect'; import type * as CfTypes from '../cf-types.ts'; declare const WsContext_base: Context.TagClass; /** * Context service providing access to the current WebSocket. * This is useful for reading WebSocket attachment data (e.g., forwarded headers) * inside RPC handlers. */ export declare class WsContext extends WsContext_base { } /** * Configuration options for setting up WebSocket RPC on a Durable Object. */ export interface DurableObjectWebSocketRpcConfig { /** The Durable Object instance to configure */ doSelf: CfTypes.DurableObject; /** * WebSocket handling mode: * - 'hibernate': Use hibernation-compatible WebSocket handling (recommended for cost optimization) * - 'accept': Use traditional WebSocket handling (not yet implemented) */ webSocketMode: 'hibernate' | 'accept'; /** * Effect RPC layer that requires `RpcServer.Protocol` (and `WsContext` if used) * and provides the RPC server runtime. * * This is typically created by: * ```typescript * RpcServer.layer(MyRpcs).pipe(Layer.provide(handlersLayer)) * ``` * * `WsContext` is provided by the WebSocket protocol layer, so handlers can access * WebSocket attachment data (e.g., forwarded headers stored after WebSocket upgrade). * * The layer requirements (`RIn`) must be a subset of `RpcServer.Protocol | WsContext`, * which are both provided by the WebSocket protocol layer. */ rpcLayer: Layer.Layer; /** Function to get access to incoming requests */ onMessage?: (msg: RpcMessage.FromClientEncoded, ws: CfTypes.WebSocket) => void; mainLayer?: Layer.Layer; } /** * Sets up WebSocket RPC functionality on a Cloudflare Durable Object with hibernation support. * * Configures hibernation-compatible WebSocket RPC communication using Effect's type-safe RPC framework. * Hibernation reduces costs by evicting DOs from memory after 10 seconds of inactivity while keeping * WebSocket connections alive and automatically restoring RPC server state when the DO wakes up. * * **Effect RPC Integration:** * - Uses Effect's RPC framework for type-safe client-server communication * - Supports streaming responses, error handling, and automatic serialization * - Handlers are defined as Effect operations for composable, testable logic * - Provides automatic message routing and protocol management * * **Hibernation Benefits:** * - Cost optimization: DOs hibernate after 10 seconds of inactivity * - Persistent connections: WebSocket connections survive hibernation * - Automatic recovery: RPC infrastructure restores seamlessly on wake-up * * **Usage Example:** * ```typescript * export class MyDurableObject extends DurableObject { * constructor(state: DurableObjectState, env: Env) { * super(state, env) * * const handlersLayer = MyRpcs.toLayer({ * Ping: ({ message }) => Effect.succeed({ response: `Pong: ${message}` }), * // ... other RPC handlers * }) * * const ServerLive = RpcServer.layer(MyRpcs).pipe(Layer.provide(handlersLayer)) * * setupDurableObjectWebSocketRpc({ * doSelf: this, * rpcLayer: ServerLive, * webSocketMode: 'hibernate', * }) * } * * async fetch(request: Request): Promise { * // Handle WebSocket upgrades * const { 0: client, 1: server } = new WebSocketPair() * this.ctx.acceptWebSocket(server) * return new Response(null, { status: 101, webSocket: client }) * } * } * ``` * * **What this function does:** * 1. Sets up WebSocket message routing and RPC protocol handling * 2. Configures hibernation-compatible WebSocket handlers (`webSocketMessage`, `webSocketClose`) * 3. Manages RPC server lifecycle (start, stop, cleanup) * 4. Handles incoming queue management for message processing * 5. Provides automatic recovery after hibernation cycles * * @param config Configuration for WebSocket RPC setup * @returns Configured WebSocket handler functions * * @see {@link https://developers.cloudflare.com/durable-objects/best-practices/websockets/ Cloudflare WebSocket Best Practices} * @see {@link https://effect-ts.github.io/effect/docs/rpc Effect RPC Documentation} */ export declare const setupDurableObjectWebSocketRpc: ({ doSelf, rpcLayer, webSocketMode, onMessage, mainLayer, }: DurableObjectWebSocketRpcConfig) => { webSocketMessage: (ws: CfTypes.WebSocket, message: string | ArrayBuffer) => void | Promise; webSocketClose: (ws: CfTypes.WebSocket, code: number, reason: string, wasClean: boolean) => void | Promise; }; /** * Arguments for creating a WebSocket RPC server protocol layer. */ export interface WsRpcServerArgs { ws: CfTypes.WebSocket; onMessage?: (message: RpcMessage.FromClientEncoded, ws: CfTypes.WebSocket) => void; /** Mailbox queue for receiving incoming messages from the WebSocket */ incomingQueue: Mailbox.Mailbox; } /** * Creates an RPC server protocol layer for WebSocket communication. * * This layer handles the low-level WebSocket protocol details for RPC communication, * including message serialization, routing, and error handling. * * Also provides `WsContext` with the current WebSocket so handlers can access * WebSocket attachment data (e.g., forwarded headers). * * @param args Configuration for WebSocket RPC protocol * @returns Effect layer that provides RPC server protocol functionality and WsContext * * @internal This is typically used internally by `setupDurableObjectWebSocketRpc` */ export declare const layerRpcServerWebsocket: (args: WsRpcServerArgs) => Layer.Layer; export {}; //# sourceMappingURL=ws-rpc-server.d.ts.map