{"version":3,"file":"wsLink-DSf4KOdW.mjs","names":["jsonEncoder: Encoder","lazyDefaults: LazyOptions","keepAliveDefaults: KeepAliveOptions","attemptIndex: number","value: T | ((...args: TArgs) => T)","opts: { message: string; cause?: unknown }","onTimeout: () => void","timeoutMs: number","resolve: (value: T | PromiseLike<T>) => void","reject: (reason?: any) => void","urlOptions: UrlOptionsWithConnectionParams","connectionParams: CallbackOrValue<TRPCRequestInfo['connectionParams']>","encoder: Encoder","message: TRPCConnectionParamsMessage","message: TRPCClientOutgoingMessage","callbacks: TCallbacks","messageId: MessageIdLike","ws: WebSocket","pingTimeout: ReturnType<typeof setTimeout> | undefined","pongTimeout: ReturnType<typeof setTimeout> | undefined","opts: WebSocketConnectionOptions","this","connection: WsConnection","opts: WebSocketClientOptions","this","requestsToAwait: Promise<void>[]","closedError: TRPCWebSocketClosedError","attemptIndex: number","ws: WebSocket","cause: unknown","message: TRPCResponseMessage","message: TRPCClientIncomingRequest","messageOrMessages: TRPCClientOutgoingMessage | TRPCClientOutgoingMessage[]","message: TRPCClientOutgoingMessage","callbacks: TCallbacks","message","opts: WebSocketClientOptions","opts: WebSocketLinkOptions<TRouter>"],"sources":["../src/links/wsLink/wsClient/encoder.ts","../src/links/wsLink/wsClient/options.ts","../src/links/internals/urlWithConnectionParams.ts","../src/links/wsLink/wsClient/utils.ts","../src/links/wsLink/wsClient/requestManager.ts","../src/links/wsLink/wsClient/wsConnection.ts","../src/links/wsLink/wsClient/wsClient.ts","../src/links/wsLink/createWsClient.ts","../src/links/wsLink/wsLink.ts"],"sourcesContent":["import type { Encoder } from '@trpc/server/adapters/ws';\n\nexport type { Encoder };\n\nexport const jsonEncoder: Encoder = {\n  encode: (data) => JSON.stringify(data),\n  decode: (data) => {\n    if (typeof data !== 'string') {\n      throw new Error(\n        'jsonEncoder received binary data. JSON uses text frames. ' +\n          'Use a binary encoder for binary data.',\n      );\n    }\n    return JSON.parse(data);\n  },\n};\n","import type { UrlOptionsWithConnectionParams } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\n\nexport interface WebSocketClientOptions extends UrlOptionsWithConnectionParams {\n  /**\n   * Ponyfill which WebSocket implementation to use\n   */\n  WebSocket?: typeof WebSocket;\n  /**\n   * The number of milliseconds before a reconnect is attempted.\n   * @default {@link exponentialBackoff}\n   */\n  retryDelayMs?: (attemptIndex: number) => number;\n  /**\n   * Triggered when a WebSocket connection is established\n   */\n  onOpen?: () => void;\n  /**\n   * Triggered when a WebSocket connection encounters an error\n   */\n  onError?: (evt?: Event) => void;\n  /**\n   * Triggered when a WebSocket connection is closed\n   */\n  onClose?: (cause?: { code?: number }) => void;\n  /**\n   * Lazy mode will close the WebSocket automatically after a period of inactivity (no messages sent or received and no pending requests)\n   */\n  lazy?: {\n    /**\n     * Enable lazy mode\n     * @default false\n     */\n    enabled: boolean;\n    /**\n     * Close the WebSocket after this many milliseconds\n     * @default 0\n     */\n    closeMs: number;\n  };\n  /**\n   * Send ping messages to the server and kill the connection if no pong message is returned\n   */\n  keepAlive?: {\n    /**\n     * @default false\n     */\n    enabled: boolean;\n    /**\n     * Send a ping message every this many milliseconds\n     * @default 5_000\n     */\n    intervalMs?: number;\n    /**\n     * Close the WebSocket after this many milliseconds if the server does not respond\n     * @default 1_000\n     */\n    pongTimeoutMs?: number;\n  };\n  /**\n   * Custom encoder for wire encoding (e.g. custom binary formats)\n   * @default jsonEncoder\n   */\n  experimental_encoder?: Encoder;\n}\n\n/**\n * Default options for lazy WebSocket connections.\n * Determines whether the connection should be established lazily and defines the delay before closure.\n */\nexport type LazyOptions = Required<NonNullable<WebSocketClientOptions['lazy']>>;\nexport const lazyDefaults: LazyOptions = {\n  enabled: false,\n  closeMs: 0,\n};\n\n/**\n * Default options for the WebSocket keep-alive mechanism.\n * Configures whether keep-alive is enabled and specifies the timeout and interval for ping-pong messages.\n */\nexport type KeepAliveOptions = Required<\n  NonNullable<WebSocketClientOptions['keepAlive']>\n>;\nexport const keepAliveDefaults: KeepAliveOptions = {\n  enabled: false,\n  pongTimeoutMs: 1_000,\n  intervalMs: 5_000,\n};\n\n/**\n * Calculates a delay for exponential backoff based on the retry attempt index.\n * The delay starts at 0 for the first attempt and doubles for each subsequent attempt,\n * capped at 30 seconds.\n */\nexport const exponentialBackoff = (attemptIndex: number) => {\n  return attemptIndex === 0 ? 0 : Math.min(1000 * 2 ** attemptIndex, 30000);\n};\n","import { type TRPCRequestInfo } from '@trpc/server/http';\n\n/**\n * Get the result of a value or function that returns a value\n * It also optionally accepts typesafe arguments for the function\n */\nexport const resultOf = <T, TArgs extends any[]>(\n  value: T | ((...args: TArgs) => T),\n  ...args: TArgs\n): T => {\n  return typeof value === 'function'\n    ? (value as (...args: TArgs) => T)(...args)\n    : value;\n};\n\n/**\n * A value that can be wrapped in callback\n */\nexport type CallbackOrValue<T> = T | (() => T | Promise<T>);\n\nexport interface UrlOptionsWithConnectionParams {\n  /**\n   * The URL to connect to (can be a function that returns a URL)\n   */\n  url: CallbackOrValue<string>;\n\n  /**\n   * Connection params that are available in `createContext()`\n   * - For `wsLink`/`wsClient`, these are sent as the first message\n   * - For `httpSubscriptionLink`, these are serialized as part of the URL under the `connectionParams` query\n   */\n  connectionParams?: CallbackOrValue<TRPCRequestInfo['connectionParams']>;\n}\n","import type {\n  TRPCConnectionParamsMessage,\n  TRPCRequestInfo,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type {\n  CallbackOrValue,\n  UrlOptionsWithConnectionParams,\n} from '../../internals/urlWithConnectionParams';\nimport { resultOf } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\n\nexport class TRPCWebSocketClosedError extends Error {\n  constructor(opts: { message: string; cause?: unknown }) {\n    super(opts.message, {\n      cause: opts.cause,\n    });\n    this.name = 'TRPCWebSocketClosedError';\n    Object.setPrototypeOf(this, TRPCWebSocketClosedError.prototype);\n  }\n}\n\n/**\n * Utility class for managing a timeout that can be started, stopped, and reset.\n * Useful for scenarios where the timeout duration is reset dynamically based on events.\n */\nexport class ResettableTimeout {\n  private timeout: ReturnType<typeof setTimeout> | undefined;\n\n  constructor(\n    private readonly onTimeout: () => void,\n    private readonly timeoutMs: number,\n  ) {}\n\n  /**\n   * Resets the current timeout, restarting it with the same duration.\n   * Does nothing if no timeout is active.\n   */\n  public reset() {\n    if (!this.timeout) return;\n\n    clearTimeout(this.timeout);\n    this.timeout = setTimeout(this.onTimeout, this.timeoutMs);\n  }\n\n  public start() {\n    clearTimeout(this.timeout);\n    this.timeout = setTimeout(this.onTimeout, this.timeoutMs);\n  }\n\n  public stop() {\n    clearTimeout(this.timeout);\n    this.timeout = undefined;\n  }\n}\n\n// Ponyfill for Promise.withResolvers https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers\nexport function withResolvers<T>() {\n  let resolve: (value: T | PromiseLike<T>) => void;\n  let reject: (reason?: any) => void;\n  const promise = new Promise<T>((res, rej) => {\n    resolve = res;\n    reject = rej;\n  });\n\n  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n  return { promise, resolve: resolve!, reject: reject! };\n}\n\n/**\n * Resolves a WebSocket URL and optionally appends connection parameters.\n *\n * If connectionParams are provided, appends 'connectionParams=1' query parameter.\n */\nexport async function prepareUrl(urlOptions: UrlOptionsWithConnectionParams) {\n  const url = await resultOf(urlOptions.url);\n\n  if (!urlOptions.connectionParams) return url;\n\n  // append `?connectionParams=1` when connection params are used\n  const prefix = url.includes('?') ? '&' : '?';\n  const connectionParams = `${prefix}connectionParams=1`;\n\n  return url + connectionParams;\n}\n\nexport async function buildConnectionMessage(\n  connectionParams: CallbackOrValue<TRPCRequestInfo['connectionParams']>,\n  encoder: Encoder,\n) {\n  const message: TRPCConnectionParamsMessage = {\n    method: 'connectionParams',\n    data: await resultOf(connectionParams),\n  };\n\n  return encoder.encode(message);\n}\n","import type { AnyTRPCRouter, inferRouterError } from '@trpc/server';\nimport type { Observer } from '@trpc/server/observable';\nimport type {\n  TRPCClientOutgoingMessage,\n  TRPCResponseMessage,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type { TRPCClientError } from '../../../TRPCClientError';\nimport { withResolvers } from './utils';\n\nexport type TCallbacks = Observer<\n  TRPCResponseMessage<unknown, inferRouterError<AnyTRPCRouter>>,\n  TRPCClientError<AnyTRPCRouter>\n>;\n\ntype MessageId = string;\ntype MessageIdLike = string | number | null;\n\n/**\n * Represents a WebSocket request managed by the RequestManager.\n * Combines the network message, a utility promise (`end`) that mirrors the lifecycle\n * handled by `callbacks`, and a set of state monitoring callbacks.\n */\ninterface Request {\n  message: TRPCClientOutgoingMessage;\n  end: Promise<void>;\n  callbacks: TCallbacks;\n}\n\n/**\n * Manages WebSocket requests, tracking their lifecycle and providing utility methods\n * for handling outgoing and pending requests.\n *\n * - **Outgoing requests**: Requests that are queued and waiting to be sent.\n * - **Pending requests**: Requests that have been sent and are in flight awaiting a response.\n *   For subscriptions, multiple responses may be received until the subscription is closed.\n */\nexport class RequestManager {\n  /**\n   * Stores requests that are outgoing, meaning they are registered but not yet sent over the WebSocket.\n   */\n  private outgoingRequests = new Array<Request & { id: MessageId }>();\n\n  /**\n   * Stores requests that are pending (in flight), meaning they have been sent over the WebSocket\n   * and are awaiting responses. For subscriptions, this includes requests\n   * that may receive multiple responses.\n   */\n  private pendingRequests: Record<MessageId, Request> = {};\n\n  /**\n   * Registers a new request by adding it to the outgoing queue and setting up\n   * callbacks for lifecycle events such as completion or error.\n   *\n   * @param message - The outgoing message to be sent.\n   * @param callbacks - Callback functions to observe the request's state.\n   * @returns A cleanup function to manually remove the request.\n   */\n  public register(message: TRPCClientOutgoingMessage, callbacks: TCallbacks) {\n    const { promise: end, resolve } = withResolvers<void>();\n\n    this.outgoingRequests.push({\n      id: String(message.id),\n      message,\n      end,\n      callbacks: {\n        next: callbacks.next,\n        complete: () => {\n          callbacks.complete();\n          resolve();\n        },\n        error: (e) => {\n          callbacks.error(e);\n          resolve();\n        },\n      },\n    });\n\n    return () => {\n      this.delete(message.id);\n      callbacks.complete();\n      resolve();\n    };\n  }\n\n  /**\n   * Deletes a request from both the outgoing and pending collections, if it exists.\n   */\n  public delete(messageId: MessageIdLike) {\n    if (messageId === null) return;\n\n    this.outgoingRequests = this.outgoingRequests.filter(\n      ({ id }) => id !== String(messageId),\n    );\n    delete this.pendingRequests[String(messageId)];\n  }\n\n  /**\n   * Moves all outgoing requests to the pending state and clears the outgoing queue.\n   *\n   * The caller is expected to handle the actual sending of the requests\n   * (e.g., sending them over the network) after this method is called.\n   *\n   * @returns The list of requests that were transitioned to the pending state.\n   */\n  public flush() {\n    const requests = this.outgoingRequests;\n    this.outgoingRequests = [];\n\n    for (const request of requests) {\n      this.pendingRequests[request.id] = request;\n    }\n    return requests;\n  }\n\n  /**\n   * Retrieves all currently pending requests, which are in flight awaiting responses\n   * or handling ongoing subscriptions.\n   */\n  public getPendingRequests() {\n    return Object.values(this.pendingRequests);\n  }\n\n  /**\n   * Retrieves a specific pending request by its message ID.\n   */\n  public getPendingRequest(messageId: MessageIdLike) {\n    if (messageId === null) return null;\n\n    return this.pendingRequests[String(messageId)];\n  }\n\n  /**\n   * Retrieves all outgoing requests, which are waiting to be sent.\n   */\n  public getOutgoingRequests() {\n    return this.outgoingRequests;\n  }\n\n  /**\n   * Retrieves all requests, both outgoing and pending, with their respective states.\n   *\n   * @returns An array of all requests with their state (\"outgoing\" or \"pending\").\n   */\n  public getRequests() {\n    return [\n      ...this.getOutgoingRequests().map((request) => ({\n        state: 'outgoing' as const,\n        message: request.message,\n        end: request.end,\n        callbacks: request.callbacks,\n      })),\n      ...this.getPendingRequests().map((request) => ({\n        state: 'pending' as const,\n        message: request.message,\n        end: request.end,\n        callbacks: request.callbacks,\n      })),\n    ];\n  }\n\n  /**\n   * Checks if there are any pending requests, including ongoing subscriptions.\n   */\n  public hasPendingRequests() {\n    return this.getPendingRequests().length > 0;\n  }\n\n  /**\n   * Checks if there are any pending subscriptions\n   */\n  public hasPendingSubscriptions() {\n    return this.getPendingRequests().some(\n      (request) => request.message.method === 'subscription',\n    );\n  }\n\n  /**\n   * Checks if there are any outgoing requests waiting to be sent.\n   */\n  public hasOutgoingRequests() {\n    return this.outgoingRequests.length > 0;\n  }\n}\n","import { behaviorSubject } from '@trpc/server/observable';\nimport type { UrlOptionsWithConnectionParams } from '../../internals/urlWithConnectionParams';\nimport type { Encoder } from './encoder';\nimport { buildConnectionMessage, prepareUrl, withResolvers } from './utils';\n\n/**\n * Opens a WebSocket connection asynchronously and returns a promise\n * that resolves when the connection is successfully established.\n * The promise rejects if an error occurs during the connection attempt.\n */\nfunction asyncWsOpen(ws: WebSocket) {\n  const { promise, resolve, reject } = withResolvers<void>();\n\n  ws.addEventListener('open', () => {\n    ws.removeEventListener('error', reject);\n    resolve();\n  });\n  ws.addEventListener('error', reject);\n\n  return promise;\n}\n\ninterface PingPongOptions {\n  /**\n   * The interval (in milliseconds) between \"PING\" messages.\n   */\n  intervalMs: number;\n\n  /**\n   * The timeout (in milliseconds) to wait for a \"PONG\" response before closing the connection.\n   */\n  pongTimeoutMs: number;\n}\n\n/**\n * Sets up a periodic ping-pong mechanism to keep the WebSocket connection alive.\n *\n * - Sends \"PING\" messages at regular intervals defined by `intervalMs`.\n * - If a \"PONG\" response is not received within the `pongTimeoutMs`, the WebSocket is closed.\n * - The ping timer resets upon receiving any message to maintain activity.\n * - Automatically starts the ping process when the WebSocket connection is opened.\n * - Cleans up timers when the WebSocket is closed.\n *\n * @param ws - The WebSocket instance to manage.\n * @param options - Configuration options for ping-pong intervals and timeouts.\n */\nfunction setupPingInterval(\n  ws: WebSocket,\n  { intervalMs, pongTimeoutMs }: PingPongOptions,\n) {\n  let pingTimeout: ReturnType<typeof setTimeout> | undefined;\n  let pongTimeout: ReturnType<typeof setTimeout> | undefined;\n\n  function start() {\n    pingTimeout = setTimeout(() => {\n      ws.send('PING');\n      pongTimeout = setTimeout(() => {\n        ws.close();\n      }, pongTimeoutMs);\n    }, intervalMs);\n  }\n\n  function reset() {\n    clearTimeout(pingTimeout);\n    start();\n  }\n\n  function pong() {\n    clearTimeout(pongTimeout);\n    reset();\n  }\n\n  ws.addEventListener('open', start);\n  ws.addEventListener('message', ({ data }) => {\n    clearTimeout(pingTimeout);\n    start();\n\n    if (data === 'PONG') {\n      pong();\n    }\n  });\n  ws.addEventListener('close', () => {\n    clearTimeout(pingTimeout);\n    clearTimeout(pongTimeout);\n  });\n}\n\nexport interface WebSocketConnectionOptions {\n  WebSocketPonyfill?: typeof WebSocket;\n  urlOptions: UrlOptionsWithConnectionParams;\n  keepAlive: PingPongOptions & {\n    enabled: boolean;\n  };\n  encoder: Encoder;\n}\n\n/**\n * Manages a WebSocket connection with support for reconnection, keep-alive mechanisms,\n * and observable state tracking.\n */\nexport class WsConnection {\n  static connectCount = 0;\n  public id = ++WsConnection.connectCount;\n\n  private readonly WebSocketPonyfill: typeof WebSocket;\n  private readonly urlOptions: UrlOptionsWithConnectionParams;\n  private readonly keepAliveOpts: WebSocketConnectionOptions['keepAlive'];\n  private readonly encoder: Encoder;\n  public readonly wsObservable = behaviorSubject<WebSocket | null>(null);\n\n  constructor(opts: WebSocketConnectionOptions) {\n    this.WebSocketPonyfill = opts.WebSocketPonyfill ?? WebSocket;\n    if (!this.WebSocketPonyfill) {\n      throw new Error(\n        \"No WebSocket implementation found - you probably don't want to use this on the server, but if you do you need to pass a `WebSocket`-ponyfill\",\n      );\n    }\n\n    this.urlOptions = opts.urlOptions;\n    this.keepAliveOpts = opts.keepAlive;\n    this.encoder = opts.encoder;\n  }\n\n  public get ws() {\n    return this.wsObservable.get();\n  }\n\n  private set ws(ws) {\n    this.wsObservable.next(ws);\n  }\n\n  /**\n   * Checks if the WebSocket connection is open and ready to communicate.\n   */\n  public isOpen(): this is { ws: WebSocket } {\n    return (\n      !!this.ws &&\n      this.ws.readyState === this.WebSocketPonyfill.OPEN &&\n      !this.openPromise\n    );\n  }\n\n  /**\n   * Checks if the WebSocket connection is closed or in the process of closing.\n   */\n  public isClosed(): this is { ws: WebSocket } {\n    return (\n      !!this.ws &&\n      (this.ws.readyState === this.WebSocketPonyfill.CLOSING ||\n        this.ws.readyState === this.WebSocketPonyfill.CLOSED)\n    );\n  }\n\n  /**\n   * Manages the WebSocket opening process, ensuring that only one open operation\n   * occurs at a time. Tracks the ongoing operation with `openPromise` to avoid\n   * redundant calls and ensure proper synchronization.\n   *\n   * Sets up the keep-alive mechanism and necessary event listeners for the connection.\n   *\n   * @returns A promise that resolves once the WebSocket connection is successfully opened.\n   */\n  private openPromise: Promise<void> | null = null;\n  public async open() {\n    if (this.openPromise) return this.openPromise;\n\n    this.id = ++WsConnection.connectCount;\n    const wsPromise = prepareUrl(this.urlOptions).then(\n      (url) => new this.WebSocketPonyfill(url),\n    );\n    this.openPromise = wsPromise.then(async (ws) => {\n      this.ws = ws;\n\n      // Set binaryType to handle both text and binary messages consistently\n      ws.binaryType = 'arraybuffer';\n\n      // Setup ping listener\n      ws.addEventListener('message', function ({ data }) {\n        if (data === 'PING') {\n          this.send('PONG');\n        }\n      });\n\n      if (this.keepAliveOpts.enabled) {\n        setupPingInterval(ws, this.keepAliveOpts);\n      }\n\n      ws.addEventListener('close', () => {\n        if (this.ws === ws) {\n          this.ws = null;\n        }\n      });\n\n      await asyncWsOpen(ws);\n\n      if (this.urlOptions.connectionParams) {\n        ws.send(\n          await buildConnectionMessage(\n            this.urlOptions.connectionParams,\n            this.encoder,\n          ),\n        );\n      }\n    });\n\n    try {\n      await this.openPromise;\n    } finally {\n      this.openPromise = null;\n    }\n  }\n\n  /**\n   * Closes the WebSocket connection gracefully.\n   * Waits for any ongoing open operation to complete before closing.\n   */\n  public async close() {\n    try {\n      await this.openPromise;\n    } finally {\n      this.ws?.close();\n    }\n  }\n}\n\n/**\n * Provides a backward-compatible representation of the connection state.\n */\nexport function backwardCompatibility(connection: WsConnection) {\n  if (connection.isOpen()) {\n    return {\n      id: connection.id,\n      state: 'open',\n      ws: connection.ws,\n    } as const;\n  }\n\n  if (connection.isClosed()) {\n    return {\n      id: connection.id,\n      state: 'closed',\n      ws: connection.ws,\n    } as const;\n  }\n\n  if (!connection.ws) {\n    return null;\n  }\n\n  return {\n    id: connection.id,\n    state: 'connecting',\n    ws: connection.ws,\n  } as const;\n}\n","import type { AnyTRPCRouter } from '@trpc/server';\nimport type { BehaviorSubject } from '@trpc/server/observable';\nimport { behaviorSubject, observable } from '@trpc/server/observable';\nimport type {\n  CombinedDataTransformer,\n  TRPCClientIncomingMessage,\n  TRPCClientIncomingRequest,\n  TRPCClientOutgoingMessage,\n  TRPCResponseMessage,\n} from '@trpc/server/unstable-core-do-not-import';\nimport {\n  run,\n  sleep,\n  transformResult,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { TRPCClientError } from '../../../TRPCClientError';\nimport type { TRPCConnectionState } from '../../internals/subscriptions';\nimport type { Operation, OperationResultEnvelope } from '../../types';\nimport type { Encoder } from './encoder';\nimport { jsonEncoder } from './encoder';\nimport type { WebSocketClientOptions } from './options';\nimport { exponentialBackoff, keepAliveDefaults, lazyDefaults } from './options';\nimport type { TCallbacks } from './requestManager';\nimport { RequestManager } from './requestManager';\nimport { ResettableTimeout, TRPCWebSocketClosedError } from './utils';\nimport { backwardCompatibility, WsConnection } from './wsConnection';\n\n/**\n * A WebSocket client for managing TRPC operations, supporting lazy initialization,\n * reconnection, keep-alive, and request management.\n */\nexport class WsClient {\n  /**\n   * Observable tracking the current connection state, including errors.\n   */\n  public readonly connectionState: BehaviorSubject<\n    TRPCConnectionState<TRPCClientError<AnyTRPCRouter>>\n  >;\n\n  private allowReconnect = false;\n  private requestManager = new RequestManager();\n  private readonly activeConnection: WsConnection;\n  private readonly reconnectRetryDelay: (attemptIndex: number) => number;\n  private inactivityTimeout: ResettableTimeout;\n  private readonly callbacks: Pick<\n    WebSocketClientOptions,\n    'onOpen' | 'onClose' | 'onError'\n  >;\n  private readonly lazyMode: boolean;\n  private readonly encoder: Encoder;\n\n  constructor(opts: WebSocketClientOptions) {\n    this.encoder = opts.experimental_encoder ?? jsonEncoder;\n    // Initialize callbacks, connection parameters, and options.\n    this.callbacks = {\n      onOpen: opts.onOpen,\n      onClose: opts.onClose,\n      onError: opts.onError,\n    };\n\n    const lazyOptions = {\n      ...lazyDefaults,\n      ...opts.lazy,\n    };\n\n    // Set up inactivity timeout for lazy connections.\n    this.inactivityTimeout = new ResettableTimeout(() => {\n      if (\n        this.requestManager.hasOutgoingRequests() ||\n        this.requestManager.hasPendingRequests()\n      ) {\n        this.inactivityTimeout.reset();\n        return;\n      }\n\n      this.close().catch(() => null);\n    }, lazyOptions.closeMs);\n\n    // Initialize the WebSocket connection.\n    this.activeConnection = new WsConnection({\n      WebSocketPonyfill: opts.WebSocket,\n      urlOptions: opts,\n      keepAlive: {\n        ...keepAliveDefaults,\n        ...opts.keepAlive,\n      },\n      encoder: this.encoder,\n    });\n    this.activeConnection.wsObservable.subscribe({\n      next: (ws) => {\n        if (!ws) return;\n        this.setupWebSocketListeners(ws);\n      },\n    });\n    this.reconnectRetryDelay = opts.retryDelayMs ?? exponentialBackoff;\n\n    this.lazyMode = lazyOptions.enabled;\n\n    this.connectionState = behaviorSubject<\n      TRPCConnectionState<TRPCClientError<AnyTRPCRouter>>\n    >({\n      type: 'state',\n      state: lazyOptions.enabled ? 'idle' : 'connecting',\n      error: null,\n    });\n\n    // Automatically open the connection if lazy mode is disabled.\n    if (!this.lazyMode) {\n      this.open().catch(() => null);\n    }\n  }\n\n  /**\n   * Opens the WebSocket connection. Handles reconnection attempts and updates\n   * the connection state accordingly.\n   */\n  private async open() {\n    this.allowReconnect = true;\n    if (this.connectionState.get().state === 'idle') {\n      this.connectionState.next({\n        type: 'state',\n        state: 'connecting',\n        error: null,\n      });\n    }\n\n    try {\n      await this.activeConnection.open();\n    } catch (error) {\n      this.reconnect(\n        new TRPCWebSocketClosedError({\n          message: 'Initialization error',\n          cause: error,\n        }),\n      );\n      return this.reconnecting;\n    }\n  }\n\n  /**\n   * Closes the WebSocket connection and stops managing requests.\n   * Ensures all outgoing and pending requests are properly finalized.\n   */\n  public async close() {\n    this.allowReconnect = false;\n    this.inactivityTimeout.stop();\n\n    const requestsToAwait: Promise<void>[] = [];\n    for (const request of this.requestManager.getRequests()) {\n      if (request.message.method === 'subscription') {\n        request.callbacks.complete();\n      } else if (request.state === 'outgoing') {\n        request.callbacks.error(\n          TRPCClientError.from(\n            new TRPCWebSocketClosedError({\n              message: 'Closed before connection was established',\n            }),\n          ),\n        );\n      } else {\n        requestsToAwait.push(request.end);\n      }\n    }\n\n    await Promise.all(requestsToAwait).catch(() => null);\n    await this.activeConnection.close().catch(() => null);\n\n    this.connectionState.next({\n      type: 'state',\n      state: 'idle',\n      error: null,\n    });\n  }\n\n  /**\n   * Method to request the server.\n   * Handles data transformation, batching of requests, and subscription lifecycle.\n   *\n   * @param op - The operation details including id, type, path, input and signal\n   * @param transformer - Data transformer for serializing requests and deserializing responses\n   * @param lastEventId - Optional ID of the last received event for subscriptions\n   *\n   * @returns An observable that emits operation results and handles cleanup\n   */\n  public request({\n    op: { id, type, path, input, signal },\n    transformer,\n    lastEventId,\n  }: {\n    op: Pick<Operation, 'id' | 'type' | 'path' | 'input' | 'signal'>;\n    transformer: CombinedDataTransformer;\n    lastEventId?: string;\n  }) {\n    return observable<\n      OperationResultEnvelope<unknown, TRPCClientError<AnyTRPCRouter>>,\n      TRPCClientError<AnyTRPCRouter>\n    >((observer) => {\n      const abort = this.batchSend(\n        {\n          id,\n          method: type,\n          params: {\n            input: transformer.input.serialize(input),\n            path,\n            lastEventId,\n          },\n        },\n        {\n          ...observer,\n          next(event) {\n            const transformed = transformResult(event, transformer.output);\n\n            if (!transformed.ok) {\n              observer.error(TRPCClientError.from(transformed.error));\n              return;\n            }\n\n            observer.next({\n              result: transformed.result,\n            });\n          },\n        },\n      );\n\n      return () => {\n        abort();\n\n        if (type === 'subscription' && this.activeConnection.isOpen()) {\n          this.send({\n            id,\n            method: 'subscription.stop',\n          });\n        }\n\n        signal?.removeEventListener('abort', abort);\n      };\n    });\n  }\n\n  public get connection() {\n    return backwardCompatibility(this.activeConnection);\n  }\n\n  /**\n   * Manages the reconnection process for the WebSocket using retry logic.\n   * Ensures that only one reconnection attempt is active at a time by tracking the current\n   * reconnection state in the `reconnecting` promise.\n   */\n  private reconnecting: Promise<void> | null = null;\n  private reconnect(closedError: TRPCWebSocketClosedError) {\n    this.connectionState.next({\n      type: 'state',\n      state: 'connecting',\n      error: TRPCClientError.from(closedError),\n    });\n    if (this.reconnecting) return;\n\n    const tryReconnect = async (attemptIndex: number) => {\n      try {\n        await sleep(this.reconnectRetryDelay(attemptIndex));\n        if (this.allowReconnect) {\n          await this.activeConnection.close();\n          await this.activeConnection.open();\n\n          if (this.requestManager.hasPendingRequests()) {\n            this.send(\n              this.requestManager\n                .getPendingRequests()\n                .map(({ message }) => message),\n            );\n          }\n        }\n        this.reconnecting = null;\n      } catch {\n        await tryReconnect(attemptIndex + 1);\n      }\n    };\n\n    this.reconnecting = tryReconnect(0);\n  }\n\n  private setupWebSocketListeners(ws: WebSocket) {\n    const handleCloseOrError = (cause: unknown) => {\n      const reqs = this.requestManager.getPendingRequests();\n      for (const { message, callbacks } of reqs) {\n        if (message.method === 'subscription') continue;\n\n        callbacks.error(\n          TRPCClientError.from(\n            cause ??\n              new TRPCWebSocketClosedError({\n                message: 'WebSocket closed',\n                cause,\n              }),\n          ),\n        );\n        this.requestManager.delete(message.id);\n      }\n    };\n\n    ws.addEventListener('open', () => {\n      run(async () => {\n        if (this.lazyMode) {\n          this.inactivityTimeout.start();\n        }\n\n        this.callbacks.onOpen?.();\n\n        this.connectionState.next({\n          type: 'state',\n          state: 'pending',\n          error: null,\n        });\n      }).catch((error) => {\n        ws.close(3000);\n        handleCloseOrError(error);\n      });\n    });\n\n    ws.addEventListener('message', ({ data }) => {\n      this.inactivityTimeout.reset();\n\n      // Handle PING/PONG as text regardless of encoder\n      if (['PING', 'PONG'].includes(data)) return;\n\n      const incomingMessage = this.encoder.decode(\n        data,\n      ) as TRPCClientIncomingMessage;\n      if ('method' in incomingMessage) {\n        this.handleIncomingRequest(incomingMessage);\n        return;\n      }\n\n      this.handleResponseMessage(incomingMessage);\n    });\n\n    ws.addEventListener('close', (event) => {\n      handleCloseOrError(event);\n      this.callbacks.onClose?.(event);\n\n      if (!this.lazyMode || this.requestManager.hasPendingSubscriptions()) {\n        this.reconnect(\n          new TRPCWebSocketClosedError({\n            message: 'WebSocket closed',\n            cause: event,\n          }),\n        );\n      }\n    });\n\n    ws.addEventListener('error', (event) => {\n      handleCloseOrError(event);\n      this.callbacks.onError?.(event);\n\n      this.reconnect(\n        new TRPCWebSocketClosedError({\n          message: 'WebSocket closed',\n          cause: event,\n        }),\n      );\n    });\n  }\n\n  private handleResponseMessage(message: TRPCResponseMessage) {\n    const request = this.requestManager.getPendingRequest(message.id);\n    if (!request) return;\n\n    request.callbacks.next(message);\n\n    let completed = true;\n    if ('result' in message && request.message.method === 'subscription') {\n      if (message.result.type === 'data') {\n        request.message.params.lastEventId = message.result.id;\n      }\n\n      if (message.result.type !== 'stopped') {\n        completed = false;\n      }\n    }\n\n    if (completed) {\n      request.callbacks.complete();\n      this.requestManager.delete(message.id);\n    }\n  }\n\n  private handleIncomingRequest(message: TRPCClientIncomingRequest) {\n    if (message.method === 'reconnect') {\n      this.reconnect(\n        new TRPCWebSocketClosedError({\n          message: 'Server requested reconnect',\n        }),\n      );\n    }\n  }\n\n  /**\n   * Sends a message or batch of messages directly to the server.\n   */\n  private send(\n    messageOrMessages: TRPCClientOutgoingMessage | TRPCClientOutgoingMessage[],\n  ) {\n    if (!this.activeConnection.isOpen()) {\n      throw new Error('Active connection is not open');\n    }\n\n    const messages =\n      messageOrMessages instanceof Array\n        ? messageOrMessages\n        : [messageOrMessages];\n    this.activeConnection.ws.send(\n      this.encoder.encode(messages.length === 1 ? messages[0] : messages),\n    );\n  }\n\n  /**\n   * Groups requests for batch sending.\n   *\n   * @returns A function to abort the batched request.\n   */\n  private batchSend(message: TRPCClientOutgoingMessage, callbacks: TCallbacks) {\n    this.inactivityTimeout.reset();\n\n    run(async () => {\n      if (!this.activeConnection.isOpen()) {\n        await this.open();\n      }\n      await sleep(0);\n\n      if (!this.requestManager.hasOutgoingRequests()) return;\n\n      this.send(this.requestManager.flush().map(({ message }) => message));\n    }).catch((err) => {\n      this.requestManager.delete(message.id);\n      callbacks.error(TRPCClientError.from(err));\n    });\n\n    return this.requestManager.register(message, callbacks);\n  }\n}\n","import type { Encoder } from './wsClient/encoder';\nimport { jsonEncoder } from './wsClient/encoder';\nimport type { WebSocketClientOptions } from './wsClient/options';\nimport { WsClient } from './wsClient/wsClient';\n\nexport function createWSClient(opts: WebSocketClientOptions) {\n  return new WsClient(opts);\n}\n\nexport type TRPCWebSocketClient = ReturnType<typeof createWSClient>;\n\nexport { jsonEncoder, type Encoder, type WebSocketClientOptions };\n","import { observable } from '@trpc/server/observable';\nimport type {\n  AnyRouter,\n  inferClientTypes,\n} from '@trpc/server/unstable-core-do-not-import';\nimport type { TransformerOptions } from '../../unstable-internals';\nimport { getTransformer } from '../../unstable-internals';\nimport type { TRPCLink } from '../types';\nimport type {\n  Encoder,\n  TRPCWebSocketClient,\n  WebSocketClientOptions,\n} from './createWsClient';\nimport { createWSClient, jsonEncoder } from './createWsClient';\n\nexport type WebSocketLinkOptions<TRouter extends AnyRouter> = {\n  client: TRPCWebSocketClient;\n} & TransformerOptions<inferClientTypes<TRouter>>;\n\nexport function wsLink<TRouter extends AnyRouter>(\n  opts: WebSocketLinkOptions<TRouter>,\n): TRPCLink<TRouter> {\n  const { client } = opts;\n  const transformer = getTransformer(opts.transformer);\n  return () => {\n    return ({ op }) => {\n      return observable((observer) => {\n        const connStateSubscription =\n          op.type === 'subscription'\n            ? client.connectionState.subscribe({\n                next(result) {\n                  observer.next({\n                    result,\n                    context: op.context,\n                  });\n                },\n              })\n            : null;\n\n        const requestSubscription = client\n          .request({\n            op,\n            transformer,\n          })\n          .subscribe(observer);\n\n        return () => {\n          requestSubscription.unsubscribe();\n          connStateSubscription?.unsubscribe();\n        };\n      });\n    };\n  };\n}\n\nexport {\n  createWSClient,\n  jsonEncoder,\n  type Encoder,\n  type TRPCWebSocketClient,\n  type WebSocketClientOptions,\n};\n"],"mappings":"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"}