/** * Browser transport for a hosted relay room — the paid-tier accelerator. * * Functionally a {@link WebSocketRelayTransport} with three additions a hosted * deployment needs: a room-aware URL convention, an auth token, and automatic * reconnect with backoff. The server it talks to is the same dumb fan-out + * disposable replay contract as {@link createRealtimeRelay} — whether that * server is a Cloudflare Durable Object, a self-hosted relay, or PartyKit is * irrelevant to this code. The name reflects the *recommended* hosted target * (DO: single-writer-per-object matches Trellis's per-graph causality), not a * hard dependency on it. * * Telos alignment: this is one swappable {@link RealtimeTransport} behind the * stable seam. Local/free presence uses {@link BroadcastChannelTransport}; this * is what you inject when "sync" is enabled. An Iroh gossip transport slots in * the same way later with zero client change. * * new DurableObjectRelayTransport({ * id: peerId, * url: 'wss://relay.example.com', * room: 'doc:42', * auth: sessionToken, * }); * * Reconnect self-heals presence for free: the room's heartbeat re-announces * local presence after the socket comes back, and this transport re-sends a * `hello` on every (re)open so the relay replays peers/chat tail immediately. */ import type { RealtimeMessage, RealtimeTransport } from './types.js'; interface SocketLike { readyState: number; send(data: string): void; close(): void; addEventListener(type: string, listener: (event: unknown) => void): void; } type SocketCtor = new (url: string) => SocketLike; export interface DurableObjectRelayReconnect { /** Max reconnect attempts after an unexpected close. 0 = unlimited. Default 0. */ maxAttempts?: number; /** Initial backoff (ms). Default 500. */ baseDelayMs?: number; /** Max backoff (ms). Default 10_000. */ maxDelayMs?: number; } export interface DurableObjectRelayTransportOptions { /** Local peer identity. */ id: string; /** * Base relay URL, e.g. `wss://relay.example.com` or * `wss://x.partykit.dev/parties/main`. The room segment and auth token are * appended per {@link buildUrl} unless you pass a fully-formed URL and omit * `room`/`auth`. */ url: string; /** Logical room id, appended as a path segment (`/{room}`) when set. */ room?: string; /** Auth token, appended as `?token=` (or `&token=`) when set. */ auth?: string; /** * Override URL assembly entirely (e.g. a different DO routing convention). * Receives the constructor options; returns the final `ws(s)://…` URL. */ buildUrl?: (opts: { url: string; room?: string; auth?: string; }) => string; /** Reconnect policy. Pass `false` to disable reconnect. */ reconnect?: DurableObjectRelayReconnect | false; /** Cap on frames buffered while disconnected (oldest dropped). Default 128. */ maxPending?: number; /** Injectable WebSocket for tests / non-browser hosts. */ WebSocketImpl?: SocketCtor; } export declare class DurableObjectRelayTransport implements RealtimeTransport { readonly id: string; private readonly url; private readonly WS; private readonly reconnect; private readonly maxPending; private ws; private handlers; private pending; private closed; private attempts; private reconnectTimer; constructor(opts: DurableObjectRelayTransportOptions); send(message: RealtimeMessage): void; onMessage(handler: (message: RealtimeMessage) => void): () => void; close(): void; private open; private scheduleReconnect; private flushPending; } export {}; //# sourceMappingURL=durable-object-relay-transport.d.ts.map