{"version":3,"file":"client.cjs","names":["#eventTarget","#debug","#broadcastChannel","#eventSource","#port","#host","#protocol","#socket","#connectToServerBus","#pendingServerEvents","#dispatcher","#connectFunction"],"sources":["../../../src/client/client.ts"],"sourcesContent":["import { parseWithBigInt, stringifyWithBigInt } from '../utils/json'\n\n// Declare the global placeholders that get replaced by the Vite plugin at transform time\n// Fall back to defaults when not using the Vite plugin or in non-transformed environments\ndeclare const __TANSTACK_DEVTOOLS_PORT__: number | undefined\ndeclare const __TANSTACK_DEVTOOLS_HOST__: string | undefined\ndeclare const __TANSTACK_DEVTOOLS_PROTOCOL__: 'http' | 'https' | undefined\n\nfunction getDefaultPort(configPort: number): number {\n  if (typeof __TANSTACK_DEVTOOLS_PORT__ !== 'undefined')\n    return __TANSTACK_DEVTOOLS_PORT__\n  return configPort\n}\n\nfunction getDefaultHost(configHost: string): string {\n  if (typeof __TANSTACK_DEVTOOLS_HOST__ !== 'undefined')\n    return __TANSTACK_DEVTOOLS_HOST__\n  return configHost\n}\n\nfunction getDefaultProtocol(\n  configProtocol: 'http' | 'https',\n): 'http' | 'https' {\n  if (typeof __TANSTACK_DEVTOOLS_PROTOCOL__ !== 'undefined')\n    return __TANSTACK_DEVTOOLS_PROTOCOL__\n  return configProtocol\n}\n\ninterface TanStackDevtoolsEvent<TEventName extends string, TPayload = any> {\n  type: TEventName\n  payload: TPayload\n  pluginId?: string // Optional pluginId to filter events by plugin\n}\n\nexport interface ClientEventBusConfig {\n  /**\n   * Optional flag to indicate if the devtools server event bus is available to connect to.\n   * This is used to determine if the devtools can connect to the server for real-time event streams.\n   */\n  connectToServerBus?: boolean\n\n  /**\n   * Optional flag to enable debug mode for the event bus.\n   */\n  debug?: boolean\n\n  /**\n   * Optional port to connect to the devtools server event bus.\n   * Defaults to 4206.\n   */\n  port?: number\n\n  /**\n   * Optional host to connect to the devtools server event bus.\n   * Defaults to 'localhost'.\n   */\n  host?: string\n\n  /**\n   * Optional protocol to use for connecting to the devtools server event bus.\n   * Defaults to 'http'. Set to 'https' when the dev server uses HTTPS.\n   */\n  protocol?: 'http' | 'https'\n}\n\nexport class ClientEventBus {\n  #port: number\n  #host: string\n  #protocol: 'http' | 'https'\n  #socket: WebSocket | null\n  #eventSource: EventSource | null\n  #eventTarget: EventTarget\n  #debug: boolean\n  #connectToServerBus: boolean\n  #broadcastChannel: BroadcastChannel | null\n  // Events emitted while the WebSocket is still establishing its connection.\n  // They are buffered here and flushed once the socket opens so early events\n  // (e.g. the marketplace's `mounted` request) are never silently dropped.\n  #pendingServerEvents: Array<string> = []\n  #dispatcher = (e: Event) => {\n    const event = (e as CustomEvent).detail\n    this.emitToServer(event)\n    this.emitToClients(event)\n  }\n  #connectFunction = () => {\n    this.debugLog(\n      'Connection request made to event-bus, replying back with success',\n    )\n    this.#eventTarget.dispatchEvent(new CustomEvent('tanstack-connect-success'))\n  }\n  constructor({\n    port = 4206,\n    host = 'localhost',\n    protocol = 'http',\n    debug = false,\n    connectToServerBus = false,\n  }: ClientEventBusConfig = {}) {\n    this.#debug = debug\n    this.#broadcastChannel = new BroadcastChannel('tanstack-devtools')\n    this.#eventSource = null\n    this.#port = getDefaultPort(port)\n    this.#host = getDefaultHost(host)\n    this.#protocol = getDefaultProtocol(protocol)\n    this.#socket = null\n    this.#connectToServerBus = connectToServerBus\n    this.#eventTarget = this.getGlobalTarget()\n    this.#broadcastChannel.onmessage = (e) => {\n      this.emitToClients(parseWithBigInt(e.data), true)\n    }\n    this.debugLog('Initializing client event bus')\n  }\n\n  private emitToClients(\n    event: TanStackDevtoolsEvent<string>,\n    fromBroadcastChannel = false,\n  ) {\n    this.debugLog('Emitting event from client bus', event)\n    const specificEvent = new CustomEvent(event.type, { detail: event })\n    this.debugLog('Emitting event to specific client listeners', event)\n    this.#eventTarget.dispatchEvent(specificEvent)\n    const globalEvent = new CustomEvent('tanstack-devtools-global', {\n      detail: event,\n    })\n    // We only emit the events if they didn't come from the broadcast channel\n    // otherwise it would infinitely send events between\n    if (!fromBroadcastChannel) {\n      this.#broadcastChannel?.postMessage(stringifyWithBigInt(event))\n    }\n    this.debugLog('Emitting event to global client listeners', event)\n    this.#eventTarget.dispatchEvent(globalEvent)\n  }\n\n  private flushPendingServerEvents() {\n    if (!this.#socket || this.#socket.readyState !== WebSocket.OPEN) {\n      return\n    }\n    const pending = this.#pendingServerEvents\n    this.#pendingServerEvents = []\n    for (const json of pending) {\n      this.debugLog('Flushing queued event to server via WS')\n      this.#socket.send(json)\n    }\n  }\n\n  private emitToServer(event: TanStackDevtoolsEvent<string, any>) {\n    const json = stringifyWithBigInt(event)\n    // try to emit it to the event bus first\n    if (this.#socket) {\n      if (this.#socket.readyState === WebSocket.OPEN) {\n        this.debugLog('Emitting event to server via WS', event)\n        this.#socket.send(json)\n      } else if (this.#socket.readyState === WebSocket.CONNECTING) {\n        // The socket handshake is still in flight. Buffer the event instead of\n        // dropping it; it will be sent once the connection opens.\n        this.debugLog('WebSocket still connecting, queueing event', event)\n        this.#pendingServerEvents.push(json)\n      }\n      // CLOSING/CLOSED sockets cannot deliver; the event is dropped.\n      return\n    }\n    // try to emit to SSE if WebSocket is not available (this will only happen on the client side)\n    if (this.#eventSource) {\n      this.debugLog('Emitting event to server via SSE', event)\n\n      fetch(`${this.#protocol}://${this.#host}:${this.#port}/__devtools/send`, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: json,\n      }).catch(() => {})\n    }\n  }\n  start() {\n    this.debugLog('Starting client event bus')\n    if (typeof window === 'undefined') {\n      return\n    }\n    if (this.#connectToServerBus) {\n      this.connect()\n    }\n    this.#eventTarget = window\n    this.#eventTarget.addEventListener(\n      'tanstack-dispatch-event',\n      this.#dispatcher,\n    )\n    this.#eventTarget.addEventListener(\n      'tanstack-connect',\n      this.#connectFunction,\n    )\n  }\n  stop() {\n    this.debugLog('Stopping client event bus')\n    if (typeof window === 'undefined') {\n      return\n    }\n    this.#eventTarget.removeEventListener(\n      'tanstack-dispatch-event',\n      this.#dispatcher,\n    )\n    this.#eventTarget.removeEventListener(\n      'tanstack-connect',\n      this.#connectFunction,\n    )\n    this.#eventSource?.close()\n    this.#socket?.close()\n    this.#socket = null\n    this.#eventSource = null\n    this.#pendingServerEvents = []\n  }\n  private getGlobalTarget() {\n    if (typeof window !== 'undefined') {\n      return window\n    }\n\n    return new EventTarget()\n  }\n  private debugLog(...messages: Array<any>) {\n    if (this.#debug) {\n      console.log('🌴 [tanstack-devtools:client-bus]', ...messages)\n    }\n  }\n  private connectSSE() {\n    this.debugLog('Connecting to SSE server')\n    this.#eventSource = new EventSource(\n      `${this.#protocol}://${this.#host}:${this.#port}/__devtools/sse`,\n    )\n    this.#eventSource.onmessage = (e) => {\n      this.debugLog('Received message from SSE server', e.data)\n      this.handleEventReceived(e.data)\n    }\n  }\n\n  private connectWebSocket() {\n    this.debugLog('Connecting to WebSocket server')\n\n    const wsProtocol = this.#protocol === 'https' ? 'wss' : 'ws'\n    this.#socket = new WebSocket(\n      `${wsProtocol}://${this.#host}:${this.#port}/__devtools/ws`,\n    )\n    this.#socket.onopen = () => {\n      this.debugLog('WebSocket connection opened')\n      this.flushPendingServerEvents()\n    }\n    this.#socket.onmessage = (e) => {\n      this.debugLog('Received message from server', e.data)\n      this.handleEventReceived(e.data)\n    }\n    this.#socket.onclose = () => {\n      this.debugLog('WebSocket connection closed')\n      this.#socket = null\n      // Drop any still-queued events — there is no open socket to deliver them.\n      this.#pendingServerEvents = []\n    }\n    this.#socket.onerror = () => {\n      this.debugLog('WebSocket connection error')\n    }\n  }\n\n  private connect() {\n    try {\n      this.connectWebSocket()\n    } catch {\n      // Do not try to connect if we're on the server side\n      if (typeof window === 'undefined') return\n      this.connectSSE()\n    }\n  }\n\n  private handleEventReceived(data: string) {\n    try {\n      const event = parseWithBigInt(data) as TanStackDevtoolsEvent<string, any>\n      this.emitToClients(event)\n    } catch {}\n  }\n}\n"],"mappings":"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"}