{"version":3,"sources":["../src/uuid.ts","../src/config.ts","../src/errors.ts","../src/voice/calls.ts","../src/voice/webrtc-browser.ts","../src/voice/voice-room.ts","../src/realtime/realtime.ts","../src/resources/attachments.ts","../src/resources/messages.ts","../src/resources/conversations.ts","../src/resources/devices.ts","../src/resources/me.ts","../src/resources/users.ts","../src/resources/call-tokens.ts","../src/voice/call-room.ts","../src/resources/ice-servers.ts","../src/rest-client.ts","../src/token-cache.ts","../src/poolse.ts","../src/version.ts"],"names":["Socket"],"mappings":"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","file":"index.cjs","sourcesContent":["// Cross-runtime UUID v4 generator. Used internally for idempotency\n// keys, client-side message ids, and upload queue local ids — all\n// places that need a unique-per-call opaque string but NOT cryptographic\n// strength (the server enforces real auth and dedup; collisions here\n// only matter for in-process bookkeeping).\n//\n// Resolution order:\n//   1. `globalThis.crypto.randomUUID()` if present (browsers in secure\n//      contexts, Node ≥ 19, Bun, Deno, Hermes ≥ 0.74 — modern path).\n//   2. `globalThis.crypto.getRandomValues()` + RFC 4122 v4 framing\n//      (covers RN apps that ship `react-native-get-random-values`).\n//   3. `Math.random()` byte fill + RFC 4122 v4 framing (last resort —\n//      enough entropy for in-process keys, never used as a security\n//      primitive).\n//\n// This function is also exported as `safeUuid` so RN consumers can\n// reuse it for their own `generateIdempotencyKey` config if they\n// want, but the default already uses it — no setup required.\n\nexport function safeUuid(): string {\n  const c = (\n    globalThis as {\n      crypto?: {\n        randomUUID?: () => string;\n        getRandomValues?: (a: Uint8Array) => Uint8Array;\n      };\n    }\n  ).crypto;\n\n  if (c?.randomUUID) return c.randomUUID();\n\n  const bytes = new Uint8Array(16);\n  if (c?.getRandomValues) {\n    c.getRandomValues(bytes);\n  } else {\n    for (let i = 0; i < 16; i++) {\n      bytes[i] = Math.floor(Math.random() * 256);\n    }\n  }\n  bytes[6] = (bytes[6]! & 0x0f) | 0x40;\n  bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n\n  const hex: string[] = [];\n  for (let i = 0; i < 16; i++) {\n    hex.push(bytes[i]!.toString(16).padStart(2, '0'));\n  }\n  return (\n    hex.slice(0, 4).join('') +\n    '-' +\n    hex.slice(4, 6).join('') +\n    '-' +\n    hex.slice(6, 8).join('') +\n    '-' +\n    hex.slice(8, 10).join('') +\n    '-' +\n    hex.slice(10).join('')\n  );\n}\n","/**\n * Hosted poolse API URL. Used as the default for `PoolseConfig.apiUrl`\n * when you don't pass one — appropriate for the vast majority of\n * integrations that target the official poolse cloud. Self-hosted /\n * staging deployments override via the `apiUrl` field.\n */\nexport const POOLSE_API_URL = 'https://api.poolse.dev';\n\nimport type { PoolseUserProfile } from './types.js';\n\n/**\n * SDK configuration passed to `new Poolse(config)`.\n */\nexport interface PoolseConfig {\n  /**\n   * Base URL of the poolse REST API. Defaults to the hosted endpoint\n   * at `https://api.poolse.dev`. Override only for self-hosted /\n   * staging deployments. MUST NOT include the `/v1` path — the SDK\n   * adds that itself.\n   */\n  apiUrl?: string;\n\n  /**\n   * Async hook the SDK calls every time it needs an `Authorization:\n   * Bearer <jwt>` header. Most apps refresh the JWT from their own\n   * backend here — the SDK never talks to poolse's `POST\n   * /v1/users/:user_id/tokens` itself (that endpoint is API-key-authed\n   * and lives on the Customer's BACKEND, not the End User's device).\n   *\n   * Return `null` to deliberately make an unauthenticated request — the\n   * server will reject it, but the SDK won't error inside `getToken`.\n   */\n  getToken: () => Promise<string | null> | string | null;\n\n  /**\n   * Optional fetch override. Browsers and Node 22+ both ship a global\n   * `fetch`, but tests can inject a mock here; bundlers in restricted\n   * environments can supply a polyfill.\n   */\n  fetch?: typeof globalThis.fetch;\n\n  /**\n   * Retry budget for transient failures (network + 5xx + 429). Defaults\n   * to 3 attempts after the initial request. Set to 0 to disable.\n   */\n  maxRetries?: number;\n\n  /**\n   * Base for the exponential backoff, in milliseconds. Each retry waits\n   * `min(maxBackoffMs, baseBackoffMs * 2^attempt)` plus jitter, OR honours\n   * the `Retry-After` header if present. Default 250 ms.\n   */\n  baseBackoffMs?: number;\n\n  /** Hard cap on a single retry delay. Default 30_000 ms. */\n  maxBackoffMs?: number;\n\n  /**\n   * Override the idempotency-key generator. Defaults to\n   * `crypto.randomUUID()`. Most apps don't need to override this — the\n   * generator is exposed mainly for deterministic tests.\n   */\n  generateIdempotencyKey?: () => string;\n\n  /**\n   * Override the WebSocket URL. Defaults to `apiUrl` with `http(s)://`\n   * swapped to `ws(s)://`, suitable when the realtime gateway shares\n   * its origin with the REST API. Set explicitly for split-host\n   * deployments (`https://api.example.com` REST + `wss://realtime.example.com` WS).\n   */\n  wsUrl?: string;\n\n  /**\n   * Path the WebSocket is mounted on. Defaults to `/socket` — matches\n   * `CaasRealtimeWeb.UserSocket`'s mount point.\n   */\n  socketPath?: string;\n\n  /**\n   * Called when the underlying socket encounters a non-fatal error\n   * (Phoenix retries internally). Useful for surfacing reconnect\n   * banners in the UI without coupling to socket internals.\n   */\n  onSocketError?: (err: Error) => void;\n\n  /**\n   * Resolve the tenant's user identifier (`external_id` — same string\n   * you pass when minting JWTs and referencing users in\n   * `member_external_ids`) to the customer's own user metadata\n   * (display name + avatar). Called by `chat.users.get(externalId)`\n   * and the `useUser(externalId)` React hook whenever a UI component\n   * needs to render a participant.\n   *\n   * The SDK caches results in-memory and dedupes concurrent calls,\n   * so a busy chat with 50 messages from 5 senders fires the\n   * resolver 5 times — once per unique sender — not 50.\n   *\n   * Customers hit their OWN backend / store here, keyed by **their own\n   * user id** (no poolse uuid mapping required):\n   *\n   *   userResolver: async (externalId) => {\n   *     const u = await fetch(`/api/users/${externalId}`).then((r) => r.json());\n   *     return { displayName: u.full_name, avatarUrl: u.avatar_url };\n   *   }\n   *\n   * Sync returns are fine when the data's already in memory:\n   *\n   *   userResolver: (externalId) => directory[externalId] ?? null\n   *\n   * Return `null` when the user can't be found — components fall back\n   * to the external_id as a label and an initials avatar.\n   */\n  userResolver?: (\n    externalId: string,\n  ) => Promise<PoolseUserProfile | null> | PoolseUserProfile | null;\n}\n\n/** Internal resolved config — all the defaults filled in. */\nexport interface ResolvedConfig {\n  apiUrl: string;\n  getToken: PoolseConfig['getToken'];\n  fetch: typeof globalThis.fetch;\n  maxRetries: number;\n  baseBackoffMs: number;\n  maxBackoffMs: number;\n  generateIdempotencyKey: () => string;\n  wsUrl: string | undefined;\n  socketPath: string;\n  onSocketError: ((err: Error) => void) | undefined;\n  userResolver: PoolseConfig['userResolver'];\n}\n\nconst DEFAULT_MAX_RETRIES = 3;\nconst DEFAULT_BASE_BACKOFF_MS = 250;\nconst DEFAULT_MAX_BACKOFF_MS = 30_000;\n\nexport function resolveConfig(config: PoolseConfig): ResolvedConfig {\n  if (typeof config.getToken !== 'function') {\n    throw new Error('Poolse: `getToken` is required and must be a function.');\n  }\n\n  const rawFetch = config.fetch ?? globalThis.fetch;\n  if (typeof rawFetch !== 'function') {\n    throw new Error(\n      'Poolse: no global `fetch` found. Provide one via `config.fetch` ' +\n        '(Node <18 or a sandboxed runtime).',\n    );\n  }\n  // Bind to globalThis so the browser's `fetch` keeps its native `this`\n  // (it throws \"Illegal invocation\" when called with any other receiver,\n  // and `this.config.fetch(...)` in the RestClient strips the binding).\n  // A consumer-supplied `config.fetch` is also bound the same way for\n  // consistency — if they want a specific receiver they should bind it\n  // themselves before passing it in.\n  const fetchFn = rawFetch.bind(globalThis);\n\n  return {\n    apiUrl: trimTrailingSlash(config.apiUrl ?? POOLSE_API_URL),\n    getToken: config.getToken,\n    fetch: fetchFn,\n    maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n    baseBackoffMs: config.baseBackoffMs ?? DEFAULT_BASE_BACKOFF_MS,\n    maxBackoffMs: config.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS,\n    generateIdempotencyKey: config.generateIdempotencyKey ?? defaultIdempotencyKey,\n    wsUrl: config.wsUrl,\n    socketPath: config.socketPath ?? '/socket',\n    onSocketError: config.onSocketError,\n    userResolver: config.userResolver,\n  };\n}\n\nfunction trimTrailingSlash(s: string): string {\n  return s.endsWith('/') ? s.slice(0, -1) : s;\n}\n\n// Delegates to `safeUuid` so the default works in every supported\n// runtime — browsers, Node, Bun, Deno, React Native (with or without\n// a crypto polyfill). Consumers can still override via\n// `config.generateIdempotencyKey` when they need a different source.\nimport { safeUuid } from './uuid.js';\n\nfunction defaultIdempotencyKey(): string {\n  return safeUuid();\n}\n","// Typed error classes the SDK raises. Callers can `instanceof`-check to\n// decide whether to retry, prompt the user to re-login, etc. — the\n// alternative (parsing error.message strings) is brittle.\n\nimport type { ErrorEnvelope } from './types.js';\n\n/** Base for any error originating in the SDK. */\nexport class PoolseError extends Error {\n  public override readonly name: string = 'PoolseError';\n\n  constructor(message: string) {\n    super(message);\n    // Restore prototype chain across the TS down-level transform.\n    Object.setPrototypeOf(this, new.target.prototype);\n  }\n}\n\n/** fetch() rejected or the server returned no response at all. */\nexport class NetworkError extends PoolseError {\n  public override readonly name: string = 'NetworkError';\n  public override readonly cause: unknown;\n\n  constructor(message: string, cause: unknown) {\n    super(message);\n    this.cause = cause;\n  }\n}\n\n/**\n * Server returned a non-2xx status with the canonical error envelope.\n * `code` is poolse's snake_case error code (e.g. `\"invalid_user_token\"`).\n */\nexport class ApiError extends PoolseError {\n  public override readonly name: string = 'ApiError';\n  public readonly status: number;\n  public readonly code: string;\n  public readonly docUrl: string;\n  public readonly details: Record<string, unknown> | undefined;\n\n  constructor(status: number, envelope: ErrorEnvelope['error']) {\n    super(`[${status}] ${envelope.code}: ${envelope.message}`);\n    this.status = status;\n    this.code = envelope.code;\n    this.docUrl = envelope.doc_url;\n    this.details = envelope.details;\n  }\n}\n\n/**\n * 429 specifically. Surfaced as its own subclass so callers can back off\n * politely without parsing the generic ApiError.\n */\nexport class RateLimitedError extends ApiError {\n  public override readonly name: string = 'RateLimitedError';\n  public readonly retryAfterMs: number;\n\n  constructor(envelope: ErrorEnvelope['error'], retryAfterMs: number) {\n    super(429, envelope);\n    this.retryAfterMs = retryAfterMs;\n  }\n}\n\n/**\n * Auth failure (401, including expired/revoked tokens). Callers should\n * refresh the JWT (via `getToken`) and retry — the SDK does NOT do this\n * automatically, because the failure could also mean \"the user signed\n * out on another tab\" and silent re-auth would hide that.\n */\nexport class AuthError extends ApiError {\n  public override readonly name: string = 'AuthError';\n\n  constructor(envelope: ErrorEnvelope['error']) {\n    super(401, envelope);\n  }\n}\n","/**\n * WhatsApp-style call invitations.\n *\n * {@link VoiceRoom} is room-shaped: you're only reachable once you've\n * already joined. Ringing somebody who is sitting idle needs a channel\n * they're always on, which is their own `user:<id>` topic — so that's\n * where the invite half of a call lives.\n *\n *     const call = await poolse.calls.invite(conversationId);\n *     // …callee's client fires onIncoming, shows a ring screen…\n *     poolse.calls.onAccepted(({ callId }) => {\n *       if (callId === call.callId) void room.join();\n *     });\n *\n * Media never touches this class. Once both sides have accepted they\n * join the voice room and negotiate exactly as the Discord-style flow\n * does.\n *\n * There is no ring timeout here on purpose: only the UI knows when it\n * gave up, and it can call {@link cancel} at that point.\n */\n\nimport type { Channel } from 'phoenix';\n\nimport { PoolseError } from '../errors.js';\nimport type {\n  CallMedia,\n  CallAccepted,\n  CallBusy,\n  CallCancelled,\n  CallDeclined,\n  CallEnded,\n  IncomingCall,\n  OutgoingCall,\n} from './types.js';\n\nexport type Unsubscribe = () => void;\n\n/** Wire shapes, snake_case as the server sends them. */\ninterface WireIncoming {\n  call_id: string;\n  conversation_id: string;\n  caller_user_id: string;\n  media?: string;\n}\ninterface WireParty {\n  call_id: string;\n  conversation_id: string;\n  user_id: string;\n}\ninterface WireInviteReply {\n  call_id: string;\n  conversation_id: string;\n  callee_user_ids?: string[];\n  media?: string;\n}\n\n/**\n * Anything unrecognised is audio.\n *\n * A server that predates the field sends nothing, and a call that rings\n * as audio is better than one that fails over how it will be rendered.\n */\nfunction toMedia(value: string | undefined): CallMedia {\n  return value === 'video' ? 'video' : 'audio';\n}\n\nexport class CallsResource {\n  /** Resolves the user channel lazily — it may not be joined yet. */\n  private readonly getChannel: () => Channel;\n\n  private readonly incoming = new Set<(c: IncomingCall) => void>();\n  private readonly accepted = new Set<(c: CallAccepted) => void>();\n  private readonly declined = new Set<(c: CallDeclined) => void>();\n  private readonly busy = new Set<(c: CallBusy) => void>();\n  private readonly cancelled = new Set<(c: CallCancelled) => void>();\n  private readonly ended = new Set<(c: CallEnded) => void>();\n\n  private bound = false;\n\n  constructor(getChannel: () => Channel) {\n    this.getChannel = getChannel;\n  }\n\n  // ── placing and answering ──────────────────────────────────────────\n\n  /**\n   * Ring every other member of a conversation. Resolves once the server\n   * has fanned the invite out, with the minted call id and who was rung\n   * — not when anyone answers; that arrives via {@link onAccepted}.\n   */\n  invite(conversationId: string, media: CallMedia = 'audio'): Promise<OutgoingCall> {\n    return this.request<WireInviteReply>('call:invite', {\n      conversation_id: conversationId,\n      media,\n    }).then((reply) => ({\n      callId: reply.call_id,\n      conversationId: reply.conversation_id,\n      calleeUserIds: reply.callee_user_ids ?? [],\n      // Echoed by the server rather than assumed, so an older deployment\n      // that ignores the field is reflected honestly instead of leaving\n      // the UI promising video it will not get.\n      media: toMedia(reply.media),\n    }));\n  }\n\n  /**\n   * Answer a ringing call. This only tells the caller you picked up —\n   * join the voice room yourself to actually connect audio.\n   */\n  async accept(call: IncomingCall): Promise<void> {\n    await this.request('call:accept', {\n      call_id: call.callId,\n      conversation_id: call.conversationId,\n      caller_user_id: call.callerUserId,\n    });\n  }\n\n  /** Reject a ringing call without joining the room. */\n  async decline(call: IncomingCall): Promise<void> {\n    await this.request('call:decline', {\n      call_id: call.callId,\n      conversation_id: call.conversationId,\n      caller_user_id: call.callerUserId,\n    });\n  }\n\n  /**\n   * Tell the caller you are already on another call.\n   *\n   * Distinct from {@link decline}: nobody chose anything, so clients\n   * send this automatically when a ring arrives mid-call. `useCalls`\n   * does it for you.\n   */\n  async markBusy(call: IncomingCall): Promise<void> {\n    await this.request('call:busy', {\n      call_id: call.callId,\n      conversation_id: call.conversationId,\n      caller_user_id: call.callerUserId,\n    });\n  }\n\n  /**\n   * End a call that is already connected.\n   *\n   * Distinct from {@link cancel}, which withdraws an unanswered invite.\n   * Without this a connected call has no end signal, so hanging up\n   * leaves the other side sitting in the room with a call screen it has\n   * no reason to close.\n   */\n  async hangUp(call: { callId: string; conversationId: string }): Promise<void> {\n    await this.request('call:hangup', {\n      call_id: call.callId,\n      conversation_id: call.conversationId,\n    });\n  }\n\n  /** Withdraw an invite you placed — hung up before anyone answered. */\n  async cancel(call: OutgoingCall): Promise<void> {\n    await this.request('call:cancel', {\n      call_id: call.callId,\n      conversation_id: call.conversationId,\n    });\n  }\n\n  // ── subscriptions ──────────────────────────────────────────────────\n\n  /** Somebody is ringing you. */\n  onIncoming(fn: (call: IncomingCall) => void): Unsubscribe {\n    this.bind();\n    this.incoming.add(fn);\n    return () => this.incoming.delete(fn) as unknown as void;\n  }\n\n  /** Your outbound call was answered — join the room now. */\n  onAccepted(fn: (call: CallAccepted) => void): Unsubscribe {\n    this.bind();\n    this.accepted.add(fn);\n    return () => this.accepted.delete(fn) as unknown as void;\n  }\n\n  /** Your outbound call was rejected. */\n  onDeclined(fn: (call: CallDeclined) => void): Unsubscribe {\n    this.bind();\n    this.declined.add(fn);\n    return () => this.declined.delete(fn) as unknown as void;\n  }\n\n  /** The person you called is already on another call. */\n  onBusy(fn: (call: CallBusy) => void): Unsubscribe {\n    this.bind();\n    this.busy.add(fn);\n    return () => this.busy.delete(fn) as unknown as void;\n  }\n\n  /** The other side ended a connected call. */\n  onEnded(fn: (call: CallEnded) => void): Unsubscribe {\n    this.bind();\n    this.ended.add(fn);\n    return () => this.ended.delete(fn) as unknown as void;\n  }\n\n  /** An inbound ring was withdrawn before you answered. */\n  onCancelled(fn: (call: CallCancelled) => void): Unsubscribe {\n    this.bind();\n    this.cancelled.add(fn);\n    return () => this.cancelled.delete(fn) as unknown as void;\n  }\n\n  // ── internals ──────────────────────────────────────────────────────\n\n  /**\n   * One Phoenix binding per event regardless of listener count; we fan\n   * out ourselves, matching how the conversation channels do it.\n   */\n  private bind(): void {\n    if (this.bound) return;\n    this.bound = true;\n    const channel = this.getChannel();\n\n    channel.on('call:incoming', (p: WireIncoming) => {\n      const call: IncomingCall = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        callerUserId: p.caller_user_id,\n        media: toMedia(p.media),\n      };\n      this.incoming.forEach((l) => l(call));\n    });\n\n    channel.on('call:accepted', (p: WireParty) => {\n      const call: CallAccepted = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        userId: p.user_id,\n      };\n      this.accepted.forEach((l) => l(call));\n    });\n\n    channel.on('call:declined', (p: WireParty) => {\n      const call: CallDeclined = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        userId: p.user_id,\n      };\n      this.declined.forEach((l) => l(call));\n    });\n\n    channel.on('call:busy', (p: WireParty) => {\n      const call: CallBusy = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        userId: p.user_id,\n      };\n      this.busy.forEach((l) => l(call));\n    });\n\n    channel.on('call:ended', (p: WireParty) => {\n      const call: CallEnded = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        userId: p.user_id,\n      };\n      this.ended.forEach((l) => l(call));\n    });\n\n    channel.on('call:cancelled', (p: WireIncoming) => {\n      const call: CallCancelled = {\n        callId: p.call_id,\n        conversationId: p.conversation_id,\n        callerUserId: p.caller_user_id,\n      };\n      this.cancelled.forEach((l) => l(call));\n    });\n  }\n\n  private request<T>(event: string, payload: Record<string, unknown>): Promise<T> {\n    return new Promise<T>((resolve, reject) => {\n      this.getChannel()\n        .push(event, payload)\n        .receive('ok', (reply: T) => resolve(reply))\n        .receive('error', (reply: { reason?: string }) =>\n          reject(new PoolseError(`${event} rejected: ${reply?.reason ?? 'unknown'}`)),\n        )\n        .receive('timeout', () => reject(new PoolseError(`${event} timed out`)));\n    });\n  }\n}\n","/**\n * Browser WebRTC binding. Used automatically when no adapter is passed\n * to {@link VoiceRoom}; React Native supplies its own via\n * `@poolse/react-native`.\n */\n\nimport type { VoiceIceServer, VoicePeerConnection, VoiceStream, WebRtcAdapter } from './types.js';\n\n/** True when this runtime can actually negotiate WebRTC. */\nexport function isWebRtcAvailable(): boolean {\n  return (\n    typeof globalThis !== 'undefined' &&\n    typeof (globalThis as { RTCPeerConnection?: unknown }).RTCPeerConnection === 'function'\n  );\n}\n\nexport function createBrowserWebRtcAdapter(): WebRtcAdapter {\n  return {\n    createPeerConnection(iceServers: VoiceIceServer[]): VoicePeerConnection {\n      // The DOM's RTCPeerConnection satisfies VoicePeerConnection\n      // structurally; the cast is only needed because our interface is\n      // deliberately narrower than the full DOM type.\n      return new RTCPeerConnection({\n        iceServers: iceServers as RTCIceServer[],\n      }) as unknown as VoicePeerConnection;\n    },\n\n    async getUserMedia(): Promise<VoiceStream> {\n      const stream = await navigator.mediaDevices.getUserMedia({\n        audio: { echoCancellation: true, noiseSuppression: true },\n      });\n      return stream as unknown as VoiceStream;\n    },\n\n    playRemoteStream(_peerId: string, stream: VoiceStream): () => void {\n      const el = document.createElement('audio');\n      el.autoplay = true;\n      // Present in the DOM (required for playback) but never laid out.\n      el.style.display = 'none';\n      el.srcObject = stream as unknown as MediaStream;\n      document.body.appendChild(el);\n\n      // Autoplay policies reject until the user has gestured. Joining a\n      // call is a gesture, so this normally resolves; swallow either way\n      // rather than failing the whole room.\n      void el.play().catch(() => {});\n\n      return () => {\n        el.srcObject = null;\n        el.remove();\n      };\n    },\n  };\n}\n","/**\n * A voice room bound to one conversation.\n *\n * Wraps poolse's `voice:conversation:<id>` channel and drives a WebRTC\n * mesh over it: one peer connection per participant, negotiated with\n * offer / answer / ICE relayed by the server.\n *\n * Two shapes are built on this:\n *\n *   * Discord-style — call `join()` directly and everyone in the room\n *     hears each other.\n *   * WhatsApp-style — ring first via `poolse.calls`, then both sides\n *     `join()` once the callee accepts.\n *\n * A mesh costs each participant N-1 upstreams, which is fine for small\n * rooms and wrong past roughly six concurrent speakers; that's where an\n * SFU belongs.\n */\n\nimport type { Channel, Socket } from 'phoenix';\n\nimport type {\n  VoiceCandidate,\n  VoiceIceServer,\n  VoiceParticipant,\n  VoicePeerConnection,\n  VoiceRoomOptions,\n  VoiceStatus,\n  VoiceStream,\n  VoiceTrack,\n  WebRtcAdapter,\n} from './types.js';\nimport { createBrowserWebRtcAdapter } from './webrtc-browser.js';\n\nexport type Unsubscribe = () => void;\n\nconst DEFAULT_ICE_SERVERS: VoiceIceServer[] = [{ urls: 'stun:stun.l.google.com:19302' }];\n\n/** RMS above this counts as speech. */\nconst SPEAKING_THRESHOLD = 0.02;\n/** Keep \"speaking\" latched this long after the level drops, so the\n *  indicator doesn't strobe between syllables. */\nconst SPEAKING_RELEASE_MS = 350;\nconst SPEAKING_POLL_MS = 100;\n\n/** Phoenix.Presence payload shape. */\ninterface PresenceEntry {\n  metas?: Array<{\n    user_id?: string;\n    mute_state?: boolean;\n    speaking_state?: boolean;\n    joined_at?: number;\n  }>;\n}\n\nexport class VoiceRoom {\n  public readonly conversationId: string;\n\n  private readonly socket: Socket;\n  private readonly webrtc: WebRtcAdapter;\n  private iceServers: VoiceIceServer[];\n  private readonly iceServersProvider: (() => Promise<VoiceIceServer[]>) | null;\n  private readonly detectSpeaking: boolean;\n\n  private channel: Channel | null = null;\n  private localStream: VoiceStream | null = null;\n  private selfId: string | null = null;\n  private status: VoiceStatus = 'idle';\n  private muted = false;\n\n  private readonly peers = new Map<string, VoicePeerConnection>();\n  private readonly sinks = new Map<string, Unsubscribe>();\n  /** Candidates that landed before their offer/answer did. */\n  private readonly pendingIce = new Map<string, VoiceCandidate[]>();\n  private readonly roster = new Map<string, Omit<VoiceParticipant, 'isSelf'>>();\n\n  /**\n   * How many callers currently hold this room open.\n   *\n   * `PoolseRealtime` hands out ONE room per conversation, so a call\n   * screen and an always-on voice bar for the same conversation share\n   * this instance — which is correct, since a user is in one audio\n   * session, not two. Without counting, whichever of them tore down\n   * first would cut the audio out from under the other.\n   */\n  private holders = 0;\n\n  private speakingTimer: ReturnType<typeof setInterval> | null = null;\n  private stopSpeakingDetection: Unsubscribe | null = null;\n\n  private readonly statusListeners = new Set<(s: VoiceStatus) => void>();\n  private readonly rosterListeners = new Set<(p: VoiceParticipant[]) => void>();\n  private readonly errorListeners = new Set<(e: Error) => void>();\n\n  constructor(conversationId: string, socket: Socket, opts: VoiceRoomOptions = {}) {\n    this.conversationId = conversationId;\n    this.socket = socket;\n    this.webrtc = opts.webrtc ?? createBrowserWebRtcAdapter();\n    this.iceServers = opts.iceServers ?? DEFAULT_ICE_SERVERS;\n    this.iceServersProvider = opts.iceServersProvider ?? null;\n    this.detectSpeaking = opts.detectSpeaking ?? true;\n  }\n\n  // ── observation ────────────────────────────────────────────────────\n\n  getStatus(): VoiceStatus {\n    return this.status;\n  }\n\n  isMuted(): boolean {\n    return this.muted;\n  }\n\n  /** Everyone in the room, oldest join first. */\n  getParticipants(): VoiceParticipant[] {\n    return [...this.roster.values()]\n      .map((p) => ({ ...p, isSelf: p.userId === this.selfId }))\n      .sort((a, b) => a.joinedAt - b.joinedAt || a.userId.localeCompare(b.userId));\n  }\n\n  onStatus(fn: (status: VoiceStatus) => void): Unsubscribe {\n    this.statusListeners.add(fn);\n    return () => this.statusListeners.delete(fn) as unknown as void;\n  }\n\n  onParticipants(fn: (participants: VoiceParticipant[]) => void): Unsubscribe {\n    this.rosterListeners.add(fn);\n    return () => this.rosterListeners.delete(fn) as unknown as void;\n  }\n\n  onError(fn: (err: Error) => void): Unsubscribe {\n    this.errorListeners.add(fn);\n    return () => this.errorListeners.delete(fn) as unknown as void;\n  }\n\n  // ── lifecycle ──────────────────────────────────────────────────────\n\n  /** Acquire the mic, join the channel, and start negotiating. */\n  async join(): Promise<void> {\n    // Already in the room: record the extra holder and reuse the\n    // session rather than opening a second channel and mesh.\n    if (this.channel) {\n      this.holders += 1;\n      return;\n    }\n\n    this.holders += 1;\n    this.setStatus('connecting');\n\n    // Resolved per join, not per construction: TURN credentials expire,\n    // so a list fetched once and reused would be rejected by the second\n    // call. This is also the only await before peers are created, which\n    // matters — `ensurePeer` reads `iceServers` synchronously.\n    await this.resolveIceServers();\n\n    try {\n      this.localStream = await this.webrtc.getUserMedia();\n    } catch (err) {\n      this.holders = Math.max(0, this.holders - 1);\n      this.setStatus('error');\n      this.emitError(new Error(`microphone unavailable: ${String(err)}`));\n      throw err;\n    }\n\n    const channel = this.socket.channel(`voice:conversation:${this.conversationId}`, {});\n    this.channel = channel;\n    this.bindChannel(channel);\n\n    await new Promise<void>((resolve, reject) => {\n      channel\n        .join()\n        .receive('ok', () => {\n          channel.push('voice:join', { muted: false, speaking: false });\n          resolve();\n        })\n        .receive('error', (reply: { reason?: string }) => {\n          const err = new Error(`voice join rejected: ${reply?.reason ?? 'unknown'}`);\n          this.setStatus('error');\n          this.emitError(err);\n          this.teardown();\n          reject(err);\n        })\n        .receive('timeout', () => {\n          const err = new Error('voice join timed out');\n          this.setStatus('error');\n          this.emitError(err);\n          this.teardown();\n          reject(err);\n        });\n    });\n  }\n\n  /** Announce departure, then drop every peer connection and the mic. */\n  leave(): void {\n    if (this.holders > 0) this.holders -= 1;\n\n    // Someone else still has the room open — hanging up a call must not\n    // silence the voice bar the user is also sitting in.\n    if (this.holders > 0) return;\n\n    this.channel?.push('voice:leave', {});\n    this.teardown();\n    this.setStatus('idle');\n  }\n\n  /** Mute or unmute the local mic. Returns the new muted state. */\n  setMuted(muted: boolean): boolean {\n    this.muted = muted;\n    for (const track of this.localStream?.getAudioTracks() ?? []) {\n      track.enabled = !muted;\n    }\n    this.channel?.push(muted ? 'voice:mute' : 'voice:unmute', { muted });\n\n    if (this.selfId) {\n      const self = this.roster.get(this.selfId);\n      // Muting also clears the speaking flag: a muted mic that was\n      // mid-word would otherwise stay lit until the next transition.\n      if (self) this.roster.set(this.selfId, { ...self, muted, speaking: false });\n      this.emitRoster();\n    }\n    return this.muted;\n  }\n\n  toggleMute(): boolean {\n    return this.setMuted(!this.muted);\n  }\n\n  // ── channel wiring ─────────────────────────────────────────────────\n\n  private bindChannel(channel: Channel): void {\n    channel.on('voice:presence_state', (state: Record<string, PresenceEntry>) => {\n      this.roster.clear();\n      for (const [userId, entry] of Object.entries(state ?? {})) {\n        const meta = entry?.metas?.[0] ?? {};\n        this.roster.set(userId, {\n          userId,\n          muted: meta.mute_state ?? false,\n          speaking: meta.speaking_state ?? false,\n          joinedAt: meta.joined_at ?? 0,\n        });\n      }\n      this.emitRoster();\n\n      for (const userId of this.roster.keys()) {\n        if (userId !== this.selfId) this.startNegotiation(userId);\n      }\n    });\n\n    channel.on('voice:joined', (payload: { user_id?: string }) => {\n      const userId = payload?.user_id;\n      if (!userId) return;\n\n      // The server pushes this to us before broadcasting it to the room,\n      // so the first one we see identifies us.\n      if (!this.selfId) {\n        this.selfId = userId;\n        this.roster.set(userId, { userId, muted: false, speaking: false, joinedAt: Date.now() });\n        this.setStatus('connected');\n        if (this.detectSpeaking && this.localStream) {\n          this.startSpeakingDetection(this.localStream);\n        }\n        this.emitRoster();\n        return;\n      }\n\n      if (userId === this.selfId) return;\n\n      if (!this.roster.has(userId)) {\n        this.roster.set(userId, { userId, muted: false, speaking: false, joinedAt: Date.now() });\n        this.emitRoster();\n      }\n      this.startNegotiation(userId);\n    });\n\n    channel.on('voice:left', (payload: { user_id?: string }) => {\n      const userId = payload?.user_id;\n      if (!userId) return;\n      this.closePeer(userId);\n      this.roster.delete(userId);\n      this.emitRoster();\n    });\n\n    channel.on('voice:mute', (payload: { user_id?: string; muted?: boolean }) => {\n      this.patchParticipant(payload?.user_id, { muted: payload?.muted ?? false });\n    });\n\n    channel.on('voice:active_speaker', (payload: { user_id?: string; speaking?: boolean }) => {\n      this.patchParticipant(payload?.user_id, { speaking: payload?.speaking ?? false });\n    });\n\n    channel.on('voice:signal', (payload: Record<string, unknown>) => {\n      void this.handleSignal(payload);\n    });\n\n    channel.on('voice:error', (payload: { reason?: string }) => {\n      this.emitError(new Error(`voice error: ${payload?.reason ?? 'unknown'}`));\n    });\n  }\n\n  /**\n   * Refresh ICE servers from the provider, if there is one.\n   *\n   * Never throws. A room that refused to connect because the ICE\n   * endpoint was briefly unreachable would be a worse outcome than one\n   * that connects without TURN — which is exactly how calls behaved\n   * before TURN existed, and works on most networks.\n   */\n  private async resolveIceServers(): Promise<void> {\n    if (!this.iceServersProvider) return;\n\n    try {\n      const servers = await this.iceServersProvider();\n      if (servers.length > 0) this.iceServers = servers;\n    } catch (err) {\n      this.emitError(new Error(`ice servers unavailable, continuing without: ${String(err)}`));\n    }\n  }\n\n  // ── negotiation ────────────────────────────────────────────────────\n\n  /**\n   * Glare control: both sides learn about each other simultaneously, so\n   * without a rule both would offer at once. The lexicographically lower\n   * user id offers and the higher answers — deterministic, no extra\n   * round trip.\n   */\n  private shouldOffer(peerId: string): boolean {\n    return this.selfId != null && this.selfId < peerId;\n  }\n\n  private startNegotiation(peerId: string): void {\n    const pc = this.ensurePeer(peerId);\n    if (!this.shouldOffer(peerId)) return;\n\n    void (async () => {\n      try {\n        const offer = await pc.createOffer();\n        await pc.setLocalDescription(offer);\n        this.sendSignal('offer', peerId, { sdp: offer.sdp });\n      } catch (err) {\n        // One failed peer must not take the room down.\n        this.emitError(new Error(`offer to ${peerId} failed: ${String(err)}`));\n      }\n    })();\n  }\n\n  private ensurePeer(peerId: string): VoicePeerConnection {\n    const existing = this.peers.get(peerId);\n    if (existing) return existing;\n\n    const pc = this.webrtc.createPeerConnection(this.iceServers);\n\n    if (this.localStream) {\n      for (const track of this.localStream.getTracks()) {\n        pc.addTrack(track, this.localStream);\n      }\n    }\n\n    pc.onicecandidate = (event) => {\n      if (!event.candidate) return;\n      this.sendSignal('ice-candidate', peerId, event.candidate);\n    };\n\n    pc.ontrack = (event) => {\n      const stream = event.streams[0];\n      if (!stream) return;\n      this.sinks.get(peerId)?.();\n      this.sinks.set(peerId, this.webrtc.playRemoteStream(peerId, stream));\n    };\n\n    this.peers.set(peerId, pc);\n    return pc;\n  }\n\n  private async handleSignal(payload: Record<string, unknown>): Promise<void> {\n    const from = payload['from_user_id'] as string | undefined;\n    const type = payload['type'] as string | undefined;\n    if (!from || !type || from === this.selfId) return;\n\n    // The channel broadcasts to the whole room, so drop directed signals\n    // addressed to somebody else.\n    const target = payload['target_user_id'] as string | undefined;\n    if (target && target !== this.selfId) return;\n\n    const data = (payload['data'] ?? {}) as Record<string, unknown>;\n    const pc = this.ensurePeer(from);\n\n    try {\n      if (type === 'offer') {\n        await pc.setRemoteDescription({ type: 'offer', sdp: data['sdp'] as string });\n        await this.flushIce(pc, from);\n        const answer = await pc.createAnswer();\n        await pc.setLocalDescription(answer);\n        this.sendSignal('answer', from, { sdp: answer.sdp });\n      } else if (type === 'answer') {\n        await pc.setRemoteDescription({ type: 'answer', sdp: data['sdp'] as string });\n        await this.flushIce(pc, from);\n      } else if (type === 'ice-candidate') {\n        const candidate = data as VoiceCandidate;\n        // Candidates routinely outrun the description they belong to,\n        // and addIceCandidate throws in that state. Queue rather than\n        // drop: a lost candidate can strand ICE, leaving a room that\n        // looks connected but carries no audio.\n        if (!pc.remoteDescription) {\n          const queued = this.pendingIce.get(from) ?? [];\n          queued.push(candidate);\n          this.pendingIce.set(from, queued);\n        } else {\n          await pc.addIceCandidate(candidate);\n        }\n      }\n    } catch (err) {\n      this.emitError(new Error(`signal (${type}) from ${from} failed: ${String(err)}`));\n    }\n  }\n\n  private async flushIce(pc: VoicePeerConnection, peerId: string): Promise<void> {\n    const queued = this.pendingIce.get(peerId);\n    if (!queued?.length) return;\n    this.pendingIce.delete(peerId);\n    for (const candidate of queued) {\n      try {\n        await pc.addIceCandidate(candidate);\n      } catch {\n        // A single stale candidate shouldn't abort the rest.\n      }\n    }\n  }\n\n  /**\n   * Every signal body travels under `data` — the server's\n   * `validate_signal_data/1` rejects the push outright when that key is\n   * missing or empty, and a rejected signal is never relayed.\n   */\n  private sendSignal(type: string, targetUserId: string, data: unknown): void {\n    this.channel?.push('voice:signal', { type, target_user_id: targetUserId, data });\n  }\n\n  // ── speaking detection ─────────────────────────────────────────────\n\n  private startSpeakingDetection(stream: VoiceStream): void {\n    const Ctor = (globalThis as { AudioContext?: typeof AudioContext }).AudioContext;\n    // React Native has no Web Audio; hosts there drive the indicator\n    // themselves (or leave it off).\n    if (!Ctor) return;\n\n    const ctx = new Ctor();\n    const source = ctx.createMediaStreamSource(stream as unknown as MediaStream);\n    const analyser = ctx.createAnalyser();\n    analyser.fftSize = 512;\n    source.connect(analyser);\n\n    const buf = new Float32Array(analyser.fftSize);\n    let speaking = false;\n    let lastLoud = 0;\n\n    this.speakingTimer = setInterval(() => {\n      analyser.getFloatTimeDomainData(buf);\n      let sum = 0;\n      for (const v of buf) sum += v * v;\n      const rms = Math.sqrt(sum / buf.length);\n\n      const now = Date.now();\n      if (!this.muted && rms > SPEAKING_THRESHOLD) lastLoud = now;\n      const next = !this.muted && now - lastLoud < SPEAKING_RELEASE_MS;\n      if (next === speaking) return;\n\n      speaking = next;\n      // Only transitions go on the wire — a per-frame push would be a\n      // flood for something that changes a few times a second.\n      this.channel?.push('voice:active_speaker', { speaking });\n      this.patchParticipant(this.selfId ?? undefined, { speaking });\n    }, SPEAKING_POLL_MS);\n\n    this.stopSpeakingDetection = () => {\n      void ctx.close().catch(() => {});\n    };\n  }\n\n  // ── teardown & emit ────────────────────────────────────────────────\n\n  private closePeer(peerId: string): void {\n    const pc = this.peers.get(peerId);\n    if (pc) {\n      pc.onicecandidate = null;\n      pc.ontrack = null;\n      pc.onconnectionstatechange = null;\n      pc.close();\n      this.peers.delete(peerId);\n    }\n    this.sinks.get(peerId)?.();\n    this.sinks.delete(peerId);\n    this.pendingIce.delete(peerId);\n  }\n\n  private teardown(): void {\n    // Reached by leave() at zero holders and by a failed join; either\n    // way nobody is holding the room once it runs.\n    this.holders = 0;\n\n    for (const peerId of [...this.peers.keys()]) this.closePeer(peerId);\n\n    if (this.speakingTimer) clearInterval(this.speakingTimer);\n    this.speakingTimer = null;\n    this.stopSpeakingDetection?.();\n    this.stopSpeakingDetection = null;\n\n    for (const track of this.localStream?.getTracks() ?? []) track.stop();\n    this.localStream = null;\n\n    this.channel?.leave();\n    this.channel = null;\n\n    this.selfId = null;\n    this.muted = false;\n    this.roster.clear();\n    this.emitRoster();\n  }\n\n  private patchParticipant(\n    userId: string | undefined,\n    patch: Partial<Omit<VoiceParticipant, 'isSelf' | 'userId'>>,\n  ): void {\n    if (!userId) return;\n    const current = this.roster.get(userId);\n    if (!current) return;\n    this.roster.set(userId, { ...current, ...patch });\n    this.emitRoster();\n  }\n\n  private setStatus(status: VoiceStatus): void {\n    if (this.status === status) return;\n    this.status = status;\n    this.statusListeners.forEach((l) => l(status));\n  }\n\n  private emitRoster(): void {\n    const snapshot = this.getParticipants();\n    this.rosterListeners.forEach((l) => l(snapshot));\n  }\n\n  private emitError(err: Error): void {\n    this.errorListeners.forEach((l) => l(err));\n  }\n}\n\nexport type { VoiceTrack };\n","// poolse Realtime — thin wrapper over Phoenix.Socket.\n//\n// Responsibilities:\n//   * Lazy connection: socket opens on the first `conversation()` / `user()` call.\n//   * Auto-reconnect with exponential backoff (default Phoenix behavior is fine).\n//   * Auto-rejoin channels on reconnect (Phoenix handles this for joined channels).\n//   * Typed listener API: `conv.onMessage((msg) => …)`.\n//   * Token refresh: re-pulls `getToken` on every (re)connect so a refreshed\n//     JWT lands the next time without manual intervention.\n//\n// Designed to be `instanceof`-stable so React hooks can mount/unmount\n// without tearing down the socket — `Poolse` holds a single instance\n// and consumers get back the same handle for the same conversation id.\n\nimport { Socket } from 'phoenix';\nimport type { Channel } from 'phoenix';\n\nimport type { ResolvedConfig } from '../config.js';\nimport { PoolseError } from '../errors.js';\nimport { CallsResource } from '../voice/calls.js';\nimport type { VoiceIceServer } from '../voice/types.js';\nimport { VoiceRoom } from '../voice/voice-room.js';\nimport type { VoiceRoomOptions } from '../voice/types.js';\nimport type { TokenCache } from '../token-cache.js';\nimport type {\n  ConversationCreatedEvent,\n  ConversationUpdatedEvent,\n  MemberReadEvent,\n  MentionEvent,\n  MessageDeletedEvent,\n  MessageNewEvent,\n  MessageUpdatedEvent,\n  PresenceSnapshot,\n  ReactionEvent,\n  RealtimeStatus,\n  TypingEvent,\n  Unsubscribe,\n} from './types.js';\n\ninterface RealtimeOptions {\n  /**\n   * WebSocket endpoint path (mounted in caas_realtime). Defaults to\n   * `'/socket'` — matches the path served by `CaasRealtimeWeb.UserSocket`.\n   */\n  socketPath?: string;\n  /**\n   * Override the Phoenix-derived WebSocket URL. Use when the realtime\n   * gateway lives on a different host than the REST API (most common\n   * in prod: `https://api.example.com` for REST, `wss://realtime.example.com`\n   * for WebSocket). When unset, the WS URL is derived from `apiUrl` by\n   * swapping http(s) → ws(s).\n   */\n  wsUrl?: string;\n  /**\n   * Resolves ICE servers for voice rooms. Wired by `Poolse` to\n   * `GET /v1/ice-servers` so TURN reaches every room without the app\n   * plumbing anything.\n   */\n  iceServersProvider?: () => Promise<VoiceIceServer[]>;\n}\n\nexport class PoolseRealtime {\n  private readonly config: ResolvedConfig;\n  private readonly tokenCache: TokenCache;\n  private readonly socketPath: string;\n  private readonly iceServersProvider: (() => Promise<VoiceIceServer[]>) | null;\n  private readonly wsUrl: string;\n\n  private socket: Socket | null = null;\n  private readonly conversations = new Map<string, ConversationChannel>();\n  private readonly voiceRooms = new Map<string, VoiceRoom>();\n  private userChannel: UserChannel | null = null;\n  private callsResource: CallsResource | null = null;\n\n  private status: RealtimeStatus = 'idle';\n  private readonly statusListeners = new Set<(s: RealtimeStatus) => void>();\n\n  constructor(config: ResolvedConfig, tokenCache: TokenCache, opts: RealtimeOptions = {}) {\n    this.config = config;\n    this.tokenCache = tokenCache;\n    this.socketPath = opts.socketPath ?? '/socket';\n    this.iceServersProvider = opts.iceServersProvider ?? null;\n    this.wsUrl = opts.wsUrl ?? deriveWsUrl(config.apiUrl);\n  }\n\n  /** Current connection status. */\n  getStatus(): RealtimeStatus {\n    return this.status;\n  }\n\n  /** Subscribe to connection-status changes. */\n  onStatus(listener: (status: RealtimeStatus) => void): Unsubscribe {\n    this.statusListeners.add(listener);\n    return () => this.statusListeners.delete(listener);\n  }\n\n  /**\n   * Open the socket (idempotent). Synchronous construction so callers\n   * can join a channel on the next line; the underlying WebSocket\n   * connects on the next tick once the JWT pre-fetch resolves.\n   *\n   * Phoenix.js invokes the `params` callback SYNCHRONOUSLY on every\n   * (re)connect and does NOT await its return value — see\n   * `phoenix/priv/static/phoenix.mjs::endPointURL`. So `params` has\n   * to read a token that's already in hand. We:\n   *\n   *   1. Construct the Socket immediately (sets `this.socket` so\n   *      concurrent `conversation()` / `user()` callers can attach\n   *      channels — Phoenix buffers joins until the socket opens).\n   *   2. Pre-fetch the JWT through `TokenCache`, which fills its\n   *      internal cache.\n   *   3. Call `socket.connect()` so phoenix.js's first handshake reads\n   *      a primed `peekToken()`.\n   *\n   * On reconnect, Phoenix calls `params()` again; the cache is still\n   * warm (default JWT exp ~1h, refresh window 30s) so `peekToken()`\n   * returns the live token. When the token genuinely expires, our\n   * REST 401 path invalidates the cache; the next reconnect's\n   * `peekToken()` is `null` and the handshake intentionally fails so\n   * the cache can re-fill on the next iteration.\n   */\n  connect(): void {\n    if (this.socket) return;\n\n    this.setStatus('connecting');\n\n    const socket = new Socket(`${this.wsUrl}${this.socketPath}`, {\n      params: () => ({ token: this.tokenCache.peekToken() ?? '' }),\n      // Phoenix's default reconnect strategy: 10ms, 50ms, 100ms, 150ms,\n      // 200ms, 250ms, 500ms, 1s, 2s, 5s — perfectly reasonable for chat.\n    });\n\n    socket.onOpen(() => this.setStatus('connected'));\n    socket.onClose(() => {\n      // `onClose` fires for both intentional disconnect and network drop.\n      // Phoenix triggers reconnect on its own for the latter; we just\n      // surface the transitional state to UIs.\n      this.setStatus(this.status === 'closed' ? 'closed' : 'reconnecting');\n    });\n    socket.onError((err) => {\n      // Errors don't tear down the socket — Phoenix retries internally.\n      // Surface as `reconnecting` so the UI can show a banner.\n      this.setStatus('reconnecting');\n      this.config.onSocketError?.(new PoolseError(`socket error: ${String(err)}`));\n    });\n\n    this.socket = socket;\n\n    // Pre-fetch the JWT, then open the socket. Channel joins called\n    // between now and socket.connect() are buffered by Phoenix and\n    // flushed on open, so callers don't need to await anything.\n    void this.tokenCache\n      .getToken()\n      .catch((err) => {\n        this.config.onSocketError?.(\n          new PoolseError(`token fetch failed before socket open: ${String(err)}`),\n        );\n      })\n      .finally(() => {\n        socket.connect();\n      });\n  }\n\n  /** Close the socket and tear down every joined channel. */\n  disconnect(): void {\n    for (const room of this.voiceRooms.values()) room.leave();\n    this.voiceRooms.clear();\n    this.setStatus('closed');\n    this.conversations.forEach((c) => c._destroy());\n    this.conversations.clear();\n    this.userChannel?._destroy();\n    this.userChannel = null;\n    if (this.socket) {\n      this.socket.disconnect();\n      this.socket = null;\n    }\n  }\n\n  /**\n   * Subscribe to a conversation. Returns a typed handle with\n   * `onMessage`, `onTyping`, etc. Reusing the same `id` returns the\n   * same handle — re-subscribing doesn't open a second channel.\n   */\n  conversation(conversationId: string): ConversationChannel {\n    const existing = this.conversations.get(conversationId);\n    if (existing) return existing;\n\n    this.connect();\n\n    if (!this.socket) {\n      throw new PoolseError('socket not initialised — call connect() first');\n    }\n\n    const channel = this.socket.channel(`conversation:${conversationId}`, {});\n    const handle = new ConversationChannel(conversationId, channel);\n    this.conversations.set(conversationId, handle);\n    handle._join();\n    return handle;\n  }\n\n  /**\n   * Subscribe to the current user's `user:<id>` channel. Only the user\n   * matching the JWT can join — poolse's UserChannel enforces this.\n   */\n  user(userId: string): UserChannel {\n    if (this.userChannel) return this.userChannel;\n\n    this.connect();\n\n    if (!this.socket) {\n      throw new PoolseError('socket not initialised — call connect() first');\n    }\n\n    const channel = this.socket.channel(`user:${userId}`, {});\n    const handle = new UserChannel(userId, channel);\n    this.userChannel = handle;\n    handle._join();\n    return handle;\n  }\n\n  /**\n   * Voice room for a conversation — the Discord-style surface. Call\n   * `join()` on the returned handle to acquire the mic and connect;\n   * reusing the same id returns the same room rather than opening a\n   * second one.\n   *\n   * Ringing somebody who hasn't joined is a separate concern; see\n   * `poolse.calls`.\n   */\n  voice(conversationId: string, opts: VoiceRoomOptions = {}): VoiceRoom {\n    const existing = this.voiceRooms.get(conversationId);\n    if (existing) return existing;\n\n    this.connect();\n\n    if (!this.socket) {\n      throw new PoolseError('socket not initialised — call connect() first');\n    }\n\n    // The app's own `iceServersProvider` wins if it passed one; ours is\n    // only a default, so a deployment with its own TURN arrangement is\n    // not overridden.\n    const room = new VoiceRoom(conversationId, this.socket, {\n      ...(this.iceServersProvider ? { iceServersProvider: this.iceServersProvider } : {}),\n      ...opts,\n    });\n    this.voiceRooms.set(conversationId, room);\n    return room;\n  }\n\n  /**\n   * Call invitations for a user — the WhatsApp-style surface. Rides the\n   * `user:<id>` topic, the one channel a client is always joined to, so\n   * a ring reaches somebody who hasn't opened a voice room yet.\n   *\n   * Takes the user id explicitly, mirroring `user(userId)`; the SDK\n   * never assumes whose token it is holding.\n   */\n  calls(userId: string): CallsResource {\n    if (this.callsResource) return this.callsResource;\n    // Resolved lazily so constructing the resource doesn't force a\n    // socket connection before the consumer subscribes to anything.\n    this.callsResource = new CallsResource(() => this.user(userId)._channel());\n    return this.callsResource;\n  }\n\n  /** Drop a conversation handle and leave the channel. */\n  leave(conversationId: string): void {\n    const handle = this.conversations.get(conversationId);\n    if (!handle) return;\n    handle._destroy();\n    this.conversations.delete(conversationId);\n  }\n\n  private setStatus(status: RealtimeStatus): void {\n    if (this.status === status) return;\n    this.status = status;\n    this.statusListeners.forEach((l) => l(status));\n  }\n}\n\n// ── ConversationChannel ────────────────────────────────────────────────\n\nexport class ConversationChannel {\n  public readonly conversationId: string;\n  private readonly channel: Channel;\n\n  // Map from event-name → set of listeners. We bind one Phoenix `.on(...)`\n  // per event name (no matter how many JS listeners) and fan out\n  // ourselves — much cheaper than re-binding on every subscription.\n  private readonly listeners = new Map<string, Set<(payload: unknown) => void>>();\n\n  // Phoenix.Presence pushes `presence_state` exactly ONCE right after\n  // join, then `presence_diff` for every change. Late subscribers\n  // (MemberList mounted after ConversationView has already joined the\n  // channel) would otherwise never see the initial snapshot and stay\n  // empty until somebody else joins or leaves. We cache the running\n  // state here and replay it on subscribe.\n  private presenceState: PresenceSnapshot = {};\n  private presenceStateSeen = false;\n\n  constructor(conversationId: string, channel: Channel) {\n    this.conversationId = conversationId;\n    this.channel = channel;\n\n    // Bind presence handlers eagerly (not via the lazy `subscribe`\n    // path) so the cache fills regardless of subscriber timing.\n    channel.on('presence_state', (payload: unknown) => {\n      this.presenceState = (payload ?? {}) as PresenceSnapshot;\n      this.presenceStateSeen = true;\n      const listeners = this.listeners.get('presence_state');\n      if (listeners) listeners.forEach((l) => l(this.presenceState));\n    });\n    channel.on('presence_diff', (payload: unknown) => {\n      const diff = (payload ?? {}) as { joins?: PresenceSnapshot; leaves?: PresenceSnapshot };\n      const next: PresenceSnapshot = { ...this.presenceState };\n      if (diff.joins) for (const [k, v] of Object.entries(diff.joins)) next[k] = v;\n      if (diff.leaves) for (const k of Object.keys(diff.leaves)) delete next[k];\n      this.presenceState = next;\n      const listeners = this.listeners.get('presence_diff');\n      if (listeners) listeners.forEach((l) => l(payload));\n    });\n  }\n\n  /** New message pushed to the conversation. */\n  onMessage(fn: (msg: MessageNewEvent) => void): Unsubscribe {\n    return this.subscribe('message:new', fn as (p: unknown) => void);\n  }\n\n  /** Existing message edited by its sender. */\n  onMessageUpdated(fn: (msg: MessageUpdatedEvent) => void): Unsubscribe {\n    return this.subscribe('message:updated', fn as (p: unknown) => void);\n  }\n\n  /** Tombstone for a soft-deleted message. */\n  onMessageDeleted(fn: (evt: MessageDeletedEvent) => void): Unsubscribe {\n    return this.subscribe('message:deleted', fn as (p: unknown) => void);\n  }\n\n  onTypingStart(fn: (evt: TypingEvent) => void): Unsubscribe {\n    return this.subscribe('typing:start', fn as (p: unknown) => void);\n  }\n\n  onTypingStop(fn: (evt: TypingEvent) => void): Unsubscribe {\n    return this.subscribe('typing:stop', fn as (p: unknown) => void);\n  }\n\n  onReactionAdded(fn: (evt: ReactionEvent) => void): Unsubscribe {\n    return this.subscribe('reaction:added', fn as (p: unknown) => void);\n  }\n\n  onReactionRemoved(fn: (evt: ReactionEvent) => void): Unsubscribe {\n    return this.subscribe('reaction:removed', fn as (p: unknown) => void);\n  }\n\n  /**\n   * A conversation member advanced their read cursor. Used to flip the\n   * sender's read-receipt glyph from \"sent\" to \"read\" in real time.\n   */\n  onMemberRead(fn: (evt: MemberReadEvent) => void): Unsubscribe {\n    return this.subscribe('member:read', fn as (p: unknown) => void);\n  }\n\n  onPresenceState(fn: (state: PresenceSnapshot) => void): Unsubscribe {\n    let set = this.listeners.get('presence_state');\n    if (!set) {\n      set = new Set();\n      this.listeners.set('presence_state', set);\n    }\n    set.add(fn as (p: unknown) => void);\n    // Replay the cached presence_state to late subscribers — Phoenix\n    // pushes it once on join and never resends, so MemberList mounted\n    // after ConversationView would otherwise stay empty.\n    if (this.presenceStateSeen) fn(this.presenceState);\n    return () => {\n      set.delete(fn as (p: unknown) => void);\n    };\n  }\n\n  onPresenceDiff(fn: (diff: PresenceSnapshot) => void): Unsubscribe {\n    return this.subscribe('presence_diff', fn as (p: unknown) => void);\n  }\n\n  /** Current presence snapshot for sync access — usually used in tests. */\n  getPresenceState(): PresenceSnapshot {\n    return this.presenceState;\n  }\n\n  /** Send a typing ping to the server. Debounced server-side. */\n  sendTyping(): void {\n    this.channel.push('typing', {});\n  }\n\n  /** @internal — called by `PoolseRealtime.conversation/1`. */\n  _join(): void {\n    this.channel.join();\n  }\n\n  /** @internal — called when the consumer leaves this conversation. */\n  _destroy(): void {\n    this.listeners.clear();\n    this.channel.leave();\n  }\n\n  private subscribe(event: string, fn: (payload: unknown) => void): Unsubscribe {\n    let set = this.listeners.get(event);\n    if (!set) {\n      set = new Set();\n      this.listeners.set(event, set);\n      this.channel.on(event, (payload: unknown) => {\n        const listeners = this.listeners.get(event);\n        if (listeners) listeners.forEach((l) => l(payload));\n      });\n    }\n    set.add(fn);\n    return () => {\n      set.delete(fn);\n    };\n  }\n}\n\n// ── UserChannel ────────────────────────────────────────────────────────\n\nexport class UserChannel {\n  public readonly userId: string;\n  private readonly channel: Channel;\n  private readonly mentionListeners = new Set<(evt: MentionEvent) => void>();\n  private readonly conversationCreatedListeners = new Set<\n    (evt: ConversationCreatedEvent) => void\n  >();\n  private readonly conversationUpdatedListeners = new Set<\n    (evt: ConversationUpdatedEvent) => void\n  >();\n  private mentionBound = false;\n  private conversationCreatedBound = false;\n  private conversationUpdatedBound = false;\n\n  constructor(userId: string, channel: Channel) {\n    this.userId = userId;\n    this.channel = channel;\n  }\n\n  /**\n   * The underlying Phoenix channel, for surfaces that push their own\n   * events on this topic (the calls resource does).\n   *\n   * @internal\n   */\n  _channel(): Channel {\n    return this.channel;\n  }\n\n  onMention(fn: (evt: MentionEvent) => void): Unsubscribe {\n    if (!this.mentionBound) {\n      this.mentionBound = true;\n      this.channel.on('mention:new', (payload: unknown) => {\n        this.mentionListeners.forEach((l) => l(payload as MentionEvent));\n      });\n    }\n    this.mentionListeners.add(fn);\n    return () => {\n      this.mentionListeners.delete(fn);\n    };\n  }\n\n  /**\n   * Subscribe to \"you've been added to a conversation\" notifications.\n   * Fires once per new membership — either because you created the\n   * conversation, or because someone added you to an existing one.\n   *\n   * Payload is the full {@link Conversation} row so consumers can\n   * prepend it to a local list without a refetch.\n   */\n  onConversationCreated(fn: (conv: ConversationCreatedEvent) => void): Unsubscribe {\n    if (!this.conversationCreatedBound) {\n      this.conversationCreatedBound = true;\n      this.channel.on('conversation:created', (payload: unknown) => {\n        this.conversationCreatedListeners.forEach((l) => l(payload as ConversationCreatedEvent));\n      });\n    }\n    this.conversationCreatedListeners.add(fn);\n    return () => {\n      this.conversationCreatedListeners.delete(fn);\n    };\n  }\n\n  /**\n   * Subscribe to \"an existing conversation changed\" notifications —\n   * fires after every `send_message` in any conversation you're a\n   * member of. Use this to update the conversation-list row's last\n   * message preview, timestamp, and unread badge without polling.\n   *\n   * Compare `evt.by_user_id` to your own user id to decide whether\n   * to increment a local unread counter; the server already keeps\n   * your own outbound messages out of your unread count.\n   */\n  onConversationUpdated(fn: (evt: ConversationUpdatedEvent) => void): Unsubscribe {\n    if (!this.conversationUpdatedBound) {\n      this.conversationUpdatedBound = true;\n      this.channel.on('conversation:updated', (payload: unknown) => {\n        this.conversationUpdatedListeners.forEach((l) => l(payload as ConversationUpdatedEvent));\n      });\n    }\n    this.conversationUpdatedListeners.add(fn);\n    return () => {\n      this.conversationUpdatedListeners.delete(fn);\n    };\n  }\n\n  /** @internal */\n  _join(): void {\n    this.channel.join();\n  }\n\n  /** @internal */\n  _destroy(): void {\n    this.mentionListeners.clear();\n    this.conversationCreatedListeners.clear();\n    this.conversationUpdatedListeners.clear();\n    this.channel.leave();\n  }\n}\n\n// ── helpers ────────────────────────────────────────────────────────────\n\nfunction deriveWsUrl(apiUrl: string): string {\n  // http(s):// → ws(s)://. Same host + port. The realtime endpoint\n  // typically shares its origin with the REST API (single VPS) but\n  // can be overridden via `RealtimeOptions.wsUrl`.\n  return apiUrl.replace(/^http/, 'ws');\n}\n","// Attachment uploads use a presigned-URL flow:\n//\n//   1. POST /v1/attachments/upload-url  → server returns a presigned\n//      PUT URL + the headers the storage backend will require, plus a\n//      `:pending` attachment row that the user can reference when\n//      sending a message.\n//   2. The client PUTs the bytes directly to the storage backend\n//      (Cloudflare R2 / S3). The bytes never touch poolse's API\n//      server — this is fast AND keeps large blobs off the app tier.\n//   3. The PUT response Status 2xx flips the attachment row from\n//      `:pending` to `:ready` (via a webhook the server subscribes\n//      to, OR opportunistically on first download — implementation\n//      detail).\n//   4. The client now sends a message referencing the attachment id.\n//\n// This module exposes that flow at two levels:\n//   * `requestUpload(attrs)` — low-level, returns the presigned URL.\n//     Use when you want full control of the PUT (custom progress,\n//     resumable uploads, chunked transfers, RN's FileSystem API).\n//   * `upload(input)` — high-level convenience that does step 1 + the\n//     PUT in one call, returning the (now-ready) attachment row.\n//     Works with browser File/Blob and any BodyInit-compatible value.\n\nimport type { RestClient } from '../rest-client.js';\nimport type {\n  Attachment,\n  AttachmentDownloadResponse,\n  AttachmentUploadRequest,\n  AttachmentUploadResponse,\n  Uuid,\n} from '../types.js';\n\n/** Input accepted by {@link AttachmentsResource.upload}. */\nexport interface AttachmentUploadInput {\n  /**\n   * The bytes to upload. Browser: pass a `File` or `Blob`. Node /\n   * Workers / Deno: a `Uint8Array`, `ArrayBuffer`, or any\n   * `BodyInit`-compatible value the runtime's `fetch` accepts as a\n   * PUT body.\n   */\n  body: BodyInit;\n  /**\n   * MIME type. MUST match what you pass as `content_type` on the\n   * upload-URL request (the storage backend signs it into the URL —\n   * a mismatch makes the PUT fail with 403).\n   */\n  contentType: string;\n  /** Total bytes — must match the bytes you actually PUT. */\n  byteSize: number;\n  /** Surfaced in download UX so saved files keep a sensible name. */\n  filename?: string;\n}\n\n/** Options accepted by every attachment method. */\nexport interface AttachmentOptions {\n  signal?: AbortSignal;\n  /**\n   * Progress callback for `upload()`. Called periodically during the\n   * PUT phase (NOT during the presigned-URL request — that's a small\n   * JSON round-trip). When set, the SDK switches to XHR for the PUT\n   * since the standard `fetch` doesn't expose upload progress events.\n   *\n   * Customers using a custom `config.fetch` (e.g. node-fetch polyfill)\n   * lose progress reporting and the callback never fires — XHR is\n   * a browser-only API.\n   */\n  onProgress?: (event: AttachmentProgressEvent) => void;\n}\n\nexport interface AttachmentProgressEvent {\n  /** Bytes uploaded so far. */\n  loaded: number;\n  /** Total bytes — equals `input.byteSize` (passed back for convenience). */\n  total: number;\n}\n\n/** Top-level `/v1/attachments` collection. */\nexport class AttachmentsResource {\n  /**\n   * The PUT to the presigned URL bypasses the SDK's authenticated\n   * REST client (presigned URLs encode their own auth and MUST NOT\n   * receive an `Authorization` header). It still respects\n   * `config.fetch` if the customer provided one — required for tests\n   * with a mock fetch, and for runtimes where `globalThis.fetch` is\n   * not the right transport.\n   */\n  constructor(\n    private readonly client: RestClient,\n    private readonly fetchFn: typeof globalThis.fetch,\n  ) {}\n\n  /**\n   * Step 1 of an upload — request a presigned PUT URL. Use this when\n   * you want to drive the PUT yourself (e.g. resumable uploads,\n   * React Native FileSystem). For the common case prefer\n   * {@link upload}, which does both steps for you.\n   */\n  requestUpload(\n    attrs: AttachmentUploadRequest,\n    opts: AttachmentOptions = {},\n  ): Promise<AttachmentUploadResponse> {\n    return this.client.request<AttachmentUploadResponse>({\n      method: 'POST',\n      path: '/v1/attachments/upload-url',\n      body: attrs,\n      ...(opts.signal ? { signal: opts.signal } : {}),\n    });\n  }\n\n  /**\n   * One-call upload: request a presigned URL, PUT the bytes to it,\n   * return the attachment row. After this resolves the attachment is\n   * ready to be referenced from a message send.\n   *\n   * ```ts\n   * // Browser <input type=\"file\">:\n   * const file = inputEl.files![0]!;\n   * const att = await chat.attachments.upload({\n   *   body: file,\n   *   contentType: file.type,\n   *   byteSize: file.size,\n   *   filename: file.name,\n   * });\n   * await chat.conversations.one(convId).messages.send({\n   *   body: 'Look at this!',\n   *   custom_data: { attachment_id: att.id },\n   * });\n   * ```\n   *\n   * Note: the PUT uses the runtime's bare `fetch` (NOT the SDK's\n   * authenticated REST client) — presigned URLs already encode their\n   * own auth and MUST NOT receive an `Authorization` header.\n   */\n  async upload(input: AttachmentUploadInput, opts: AttachmentOptions = {}): Promise<Attachment> {\n    const req: AttachmentUploadRequest = {\n      content_type: input.contentType,\n      byte_size: input.byteSize,\n      ...(input.filename !== undefined ? { original_filename: input.filename } : {}),\n    };\n\n    const { attachment, upload } = await this.requestUpload(req, opts);\n\n    // Progress reporting requires XHR — `fetch` doesn't expose upload\n    // events. Drop to XHR only when the caller actually wants progress;\n    // otherwise stick with `fetch` (handles streams + Node polyfills\n    // that XHR doesn't).\n    if (opts.onProgress && typeof XMLHttpRequest !== 'undefined') {\n      await xhrPut(upload.url, upload.method.toUpperCase(), upload.headers, input.body, {\n        byteSize: input.byteSize,\n        onProgress: opts.onProgress,\n        ...(opts.signal ? { signal: opts.signal } : {}),\n      });\n      return attachment;\n    }\n\n    const putInit: RequestInit = {\n      method: upload.method.toUpperCase(),\n      headers: upload.headers,\n      body: input.body,\n      ...(opts.signal ? { signal: opts.signal } : {}),\n    };\n\n    const res = await this.fetchFn(upload.url, putInit);\n    if (!res.ok) {\n      throw new Error(\n        `Poolse: presigned upload PUT failed (${res.status}) for attachment ${attachment.id}`,\n      );\n    }\n    return attachment;\n  }\n\n  /** Returns a handle for further operations on a single attachment. */\n  one(id: Uuid): AttachmentHandle {\n    return new AttachmentHandle(this.client, id);\n  }\n}\n\n/** Wraps an attachment id for download-url + delete. */\nexport class AttachmentHandle {\n  constructor(\n    private readonly client: RestClient,\n    public readonly id: Uuid,\n  ) {}\n\n  /**\n   * Request a presigned GET URL (~1h TTL). Conversation-member-gated\n   * server-side. Useful when rendering files in chat: cache the URL\n   * client-side until close to expiry, then re-fetch.\n   */\n  downloadUrl(opts: AttachmentOptions = {}): Promise<AttachmentDownloadResponse> {\n    return this.client.request<AttachmentDownloadResponse>({\n      method: 'GET',\n      path: `/v1/attachments/${this.id}/download-url`,\n      ...(opts.signal ? { signal: opts.signal } : {}),\n    });\n  }\n\n  /**\n   * Delete the attachment row + best-effort bucket object delete.\n   * Authz: uploader (while still `:pending`) or message-sender / conv\n   * owner-admin (once linked).\n   */\n  delete(opts: AttachmentOptions = {}): Promise<void> {\n    return this.client.request<void>({\n      method: 'DELETE',\n      path: `/v1/attachments/${this.id}`,\n      ...(opts.signal ? { signal: opts.signal } : {}),\n    });\n  }\n}\n\n/**\n * XHR-based PUT with upload progress events. Used by `upload()` when\n * the caller passes an `onProgress` callback — `fetch` doesn't\n * expose upload progress.\n *\n * Browser-only: tests + Node polyfills don't define XMLHttpRequest,\n * so the caller path that selects XHR vs fetch checks\n * `typeof XMLHttpRequest !== 'undefined'` upstream.\n */\nfunction xhrPut(\n  url: string,\n  method: string,\n  headers: Record<string, string>,\n  body: BodyInit,\n  opts: {\n    byteSize: number;\n    onProgress: (e: AttachmentProgressEvent) => void;\n    signal?: AbortSignal;\n  },\n): Promise<void> {\n  return new Promise((resolve, reject) => {\n    const xhr = new XMLHttpRequest();\n    xhr.open(method, url);\n    for (const [k, v] of Object.entries(headers)) {\n      try {\n        xhr.setRequestHeader(k, v);\n      } catch {\n        // Some browsers refuse to set forbidden headers (Content-Length,\n        // etc.). The presigned URL still works without them.\n      }\n    }\n    xhr.upload.onprogress = (e) => {\n      // `lengthComputable` is true on R2 / S3; fall back to byteSize\n      // for older browsers that don't expose `total`.\n      const total = e.lengthComputable ? e.total : opts.byteSize;\n      opts.onProgress({ loaded: e.loaded, total });\n    };\n    xhr.onload = () => {\n      if (xhr.status >= 200 && xhr.status < 300) resolve();\n      else\n        reject(new Error(`Poolse: presigned upload PUT failed (${xhr.status} ${xhr.statusText})`));\n    };\n    xhr.onerror = () => reject(new Error('Poolse: presigned upload PUT failed (network error)'));\n    xhr.onabort = () => {\n      // Surface as DOMException('AbortError') so callers can detect.\n      reject(new DOMException('Upload aborted', 'AbortError'));\n    };\n    if (opts.signal) {\n      if (opts.signal.aborted) {\n        xhr.abort();\n        return;\n      }\n      opts.signal.addEventListener('abort', () => xhr.abort(), { once: true });\n    }\n    // body must be XHR-compatible: Blob, File, FormData, string,\n    // ArrayBufferView. Customers using a streaming body via fetch\n    // wouldn't pass `onProgress` (we'd be on the fetch path).\n    xhr.send(body as XMLHttpRequestBodyInit);\n  });\n}\n","import type { RestClient } from '../rest-client.js';\nimport type {\n  Message,\n  MessageCreateRequest,\n  MessageList,\n  MessageUpdateRequest,\n  ReactionRequest,\n  Uuid,\n} from '../types.js';\nimport { safeUuid } from '../uuid.js';\n\n/** Per-conversation message collection: send, list, mark-read. */\nexport class ConversationMessages {\n  constructor(\n    private readonly client: RestClient,\n    private readonly conversationId: Uuid,\n  ) {}\n\n  list(opts: { limit?: number; before?: number } = {}, signal?: AbortSignal): Promise<MessageList> {\n    return this.client.request<MessageList>({\n      method: 'GET',\n      path: `/v1/conversations/${this.conversationId}/messages`,\n      query: {\n        ...(opts.limit !== undefined ? { limit: opts.limit } : {}),\n        ...(opts.before !== undefined ? { before: opts.before } : {}),\n      },\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  /**\n   * Send a message to this conversation.\n   *\n   * If `attrs.id` is omitted the SDK generates a v4 UUID and uses it\n   * as both the wire-level idempotency key AND the literal message.id\n   * the server stores. Two side-effects that make a real-time UI\n   * trivial:\n   *\n   *   * Resending the same `id` (e.g. a network-retry) returns the\n   *     ORIGINAL message instead of inserting a duplicate.\n   *   * The realtime `message:new` broadcast carries this same id,\n   *     so an optimistic UI can pre-render the row under the final id\n   *     and dedup by id alone — no client/server id swap needed.\n   *\n   * Pass an explicit `attrs.id` only when you generated it yourself\n   * upstream (e.g. you already render an optimistic row in your hook\n   * and want the server to confirm under the same key).\n   */\n  send(attrs: MessageCreateRequest, signal?: AbortSignal): Promise<Message> {\n    const body: MessageCreateRequest =\n      attrs.id !== undefined ? attrs : { ...attrs, id: generateClientMessageId() };\n    return this.client.request<Message>({\n      method: 'POST',\n      path: `/v1/conversations/${this.conversationId}/messages`,\n      body,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  markRead(messageId: Uuid, signal?: AbortSignal): Promise<void> {\n    return this.client.request<void>({\n      method: 'POST',\n      path: `/v1/conversations/${this.conversationId}/read`,\n      body: { message_id: messageId },\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n\n/** Per-message operations: edit, delete, react, list replies. */\nexport class MessageHandle {\n  constructor(\n    private readonly client: RestClient,\n    public readonly id: Uuid,\n  ) {}\n\n  update(attrs: MessageUpdateRequest, signal?: AbortSignal): Promise<Message> {\n    return this.client.request<Message>({\n      method: 'PATCH',\n      path: `/v1/messages/${this.id}`,\n      body: attrs,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  delete(signal?: AbortSignal): Promise<void> {\n    return this.client.request<void>({\n      method: 'DELETE',\n      path: `/v1/messages/${this.id}`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  replies(\n    opts: { limit?: number; after?: number } = {},\n    signal?: AbortSignal,\n  ): Promise<MessageList> {\n    return this.client.request<MessageList>({\n      method: 'GET',\n      path: `/v1/messages/${this.id}/replies`,\n      query: {\n        ...(opts.limit !== undefined ? { limit: opts.limit } : {}),\n        ...(opts.after !== undefined ? { after: opts.after } : {}),\n      },\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  addReaction(emoji: string, signal?: AbortSignal): Promise<Message> {\n    const body: ReactionRequest = { emoji };\n    return this.client.request<Message>({\n      method: 'POST',\n      path: `/v1/messages/${this.id}/reactions`,\n      body,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  removeReaction(emoji: string, signal?: AbortSignal): Promise<Message> {\n    return this.client.request<Message>({\n      method: 'DELETE',\n      path: `/v1/messages/${this.id}/reactions/${encodeURIComponent(emoji)}`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n\n/** Top-level `/v1/messages` namespace — accessed via `chat.messages(id)`. */\nexport class MessagesResource {\n  constructor(private readonly client: RestClient) {}\n\n  one(id: Uuid): MessageHandle {\n    return new MessageHandle(this.client, id);\n  }\n}\n\n/**\n * Client-side message id generator. Delegates to the SDK's `safeUuid`\n * which works in every supported runtime (browsers, Node ≥ 19, RN /\n * Hermes — with or without a crypto polyfill). Server enforces real\n * auth + dedup; in-process collisions are effectively impossible at\n * any practical message volume.\n */\nfunction generateClientMessageId(): Uuid {\n  return safeUuid();\n}\n","import type { RestClient } from '../rest-client.js';\nimport { ConversationMessages } from './messages.js';\nimport type {\n  Conversation,\n  ConversationCreateRequest,\n  ConversationList,\n  ConversationUpdateRequest,\n  MemberRole,\n  Membership,\n  MembershipList,\n  Uuid,\n} from '../types.js';\n\n/** Optional knobs accepted by every member-add call. */\nexport interface AddMemberOptions {\n  /** Membership role — defaults to `\"member\"` server-side. */\n  role?: MemberRole;\n  /** AbortSignal for caller-driven cancellation. */\n  signal?: AbortSignal;\n}\n\n/** Wraps a single conversation by id — used as the entry point for sub-resources. */\nexport class ConversationHandle {\n  /**\n   * Message ops scoped to this conversation: `list`, `send`, `markRead`.\n   * Lazy: constructed on first access so an idle handle stays cheap.\n   */\n  public readonly messages: ConversationMessages;\n\n  constructor(\n    private readonly client: RestClient,\n    public readonly id: Uuid,\n  ) {\n    this.messages = new ConversationMessages(this.client, this.id);\n  }\n\n  show(signal?: AbortSignal): Promise<Conversation> {\n    return this.client.request<Conversation>({\n      method: 'GET',\n      path: `/v1/conversations/${this.id}`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  update(attrs: ConversationUpdateRequest, signal?: AbortSignal): Promise<Conversation> {\n    return this.client.request<Conversation>({\n      method: 'PATCH',\n      path: `/v1/conversations/${this.id}`,\n      body: attrs,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  // ── members ────────────────────────────────────────────────────────────\n\n  listMembers(signal?: AbortSignal): Promise<MembershipList> {\n    return this.client.request<MembershipList>({\n      method: 'GET',\n      path: `/v1/conversations/${this.id}/members`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  /**\n   * Add multiple users to this conversation in one round-trip.\n   *\n   * `externalIds` are the stable customer-side identifiers you passed\n   * to `POST /v1/users` when creating each user — the server resolves\n   * them to internal user_ids and creates one membership row per id.\n   *\n   * Requires `:manage_members` on this conversation (owner or admin).\n   *\n   * ```ts\n   * await chat.conversations.one(convId).addMembers(['alice', 'bob']);\n   * ```\n   */\n  addMembers(externalIds: string[], opts: AddMemberOptions = {}): Promise<MembershipList> {\n    return this.client.request<MembershipList>({\n      method: 'POST',\n      path: `/v1/conversations/${this.id}/members`,\n      body: {\n        external_ids: externalIds,\n        ...(opts.role !== undefined ? { role: opts.role } : {}),\n      },\n      ...(opts.signal ? { signal: opts.signal } : {}),\n    });\n  }\n\n  /**\n   * Add a single user. Convenience wrapper around {@link addMembers}\n   * that unwraps the returned list to the single membership row.\n   *\n   * ```ts\n   * const m = await chat.conversations.one(convId).addMember('alice');\n   * ```\n   */\n  async addMember(externalId: string, opts: AddMemberOptions = {}): Promise<Membership> {\n    const list = await this.addMembers([externalId], opts);\n    const row = list.data[0];\n    if (!row) {\n      // Server should always return one membership per external_id;\n      // empty data here means a contract violation, not a missing user\n      // (the latter surfaces as a 422 user_not_found error).\n      throw new Error('Poolse: addMember succeeded but server returned no membership row.');\n    }\n    return row;\n  }\n\n  removeMember(userId: Uuid, signal?: AbortSignal): Promise<void> {\n    return this.client.request<void>({\n      method: 'DELETE',\n      path: `/v1/conversations/${this.id}/members/${userId}`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n\n/** Top-level `/v1/conversations` collection. */\nexport class ConversationsResource {\n  constructor(private readonly client: RestClient) {}\n\n  list(signal?: AbortSignal): Promise<ConversationList> {\n    return this.client.request<ConversationList>({\n      method: 'GET',\n      path: '/v1/conversations',\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  create(attrs: ConversationCreateRequest, signal?: AbortSignal): Promise<Conversation> {\n    return this.client.request<Conversation>({\n      method: 'POST',\n      path: '/v1/conversations',\n      body: attrs,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  /** Returns a handle for further operations on a single conversation. */\n  one(id: Uuid): ConversationHandle {\n    return new ConversationHandle(this.client, id);\n  }\n}\n","import type { RestClient } from '../rest-client.js';\n\n/** Which push service a token belongs to. */\nexport type DevicePlatform = 'ios' | 'android';\n\n/**\n * Which APNs environment issued the token. The two have disjoint token\n * spaces — a sandbox token is rejected by production APNs and vice\n * versa — so a debug build must say `sandbox` or its pushes vanish.\n */\nexport type DeviceEnvironment = 'production' | 'sandbox';\n\nexport interface RegisterDeviceRequest {\n  /**\n   * On iOS this MUST be the **PushKit VoIP token**, not the regular\n   * APNs token. Apple issues them separately and a VoIP push aimed at a\n   * normal token is discarded without an error.\n   */\n  token: string;\n  platform: DevicePlatform;\n  /** Defaults to `production` server-side. */\n  environment?: DeviceEnvironment;\n}\n\n/** A registered device, minus the token itself. */\nexport interface Device {\n  id: string;\n  tenant_id: string;\n  user_id: string;\n  platform: DevicePlatform;\n  environment: DeviceEnvironment;\n  last_registered_at: string | null;\n  inserted_at: string;\n  updated_at: string;\n}\n\n/**\n * `/v1/devices` — where a call should ring when the app isn't running.\n *\n * The realtime `call:incoming` event only reaches a live WebSocket, and\n * iOS suspends sockets on background and drops them on close. Registering\n * here is what lets the server wake the app with a VoIP push instead.\n */\nexport class DevicesResource {\n  constructor(private readonly client: RestClient) {}\n\n  /**\n   * POST /v1/devices\n   *\n   * Idempotent — PushKit hands the app a token on every launch, so call\n   * this each time rather than trying to remember whether you already\n   * did. Re-registering also refreshes the server's staleness clock.\n   */\n  register(body: RegisterDeviceRequest, signal?: AbortSignal): Promise<Device> {\n    return this.client.request<Device>({\n      method: 'POST',\n      path: '/v1/devices',\n      body,\n      ...(signal ? { signal } : {}),\n    });\n  }\n\n  /**\n   * DELETE /v1/devices/:token\n   *\n   * Call on sign-out, or the handset keeps ringing for a user who is no\n   * longer on it.\n   */\n  unregister(token: string, signal?: AbortSignal): Promise<void> {\n    return this.client.request<void>({\n      method: 'DELETE',\n      path: `/v1/devices/${encodeURIComponent(token)}`,\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n","import type { RestClient } from '../rest-client.js';\nimport type { Me } from '../types.js';\n\n/** `/v1/me` — the End-User identity behind the presented JWT. */\nexport class MeResource {\n  constructor(private readonly client: RestClient) {}\n\n  /** GET /v1/me */\n  show(signal?: AbortSignal): Promise<Me> {\n    return this.client.request<Me>({\n      method: 'GET',\n      path: '/v1/me',\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n","// Customer-supplied user metadata, cached — keyed by the tenant's\n// `external_id` (the same string the customer passes when minting\n// JWTs or referencing users in member lists).\n//\n// poolse has no concept of a \"user profile\" — names and avatars\n// live in the customer's app, not ours. `UsersResource` wraps the\n// `userResolver` the customer passed into `PoolseConfig` with:\n//\n//   * an in-memory cache keyed by external_id\n//   * concurrent-request dedup (10 bubbles asking for the same user\n//     on the same tick fire ONE resolver call)\n//   * subscription so React (or any other UI) can re-render when a\n//     pending lookup resolves\n//\n// Negative results (resolver returned null, threw, or the customer\n// didn't configure a resolver at all) are cached too so we don't\n// retry on every mount. Customers who want to invalidate the cache\n// can call `chat.users.invalidate(externalId)` after their backend's\n// user data changes (or `invalidateAll()` after a sign-out / tenant\n// swap).\n\nimport type { ResolvedConfig } from '../config.js';\nimport type { PoolseUserProfile } from '../types.js';\n\ntype Listener = () => void;\n\nexport class UsersResource {\n  private readonly cache = new Map<string, PoolseUserProfile | null>();\n  private readonly pending = new Map<string, Promise<PoolseUserProfile | null>>();\n  private readonly listeners = new Map<string, Set<Listener>>();\n\n  constructor(private readonly config: ResolvedConfig) {}\n\n  /**\n   * Get the cached value if present. Returns `undefined` to mean\n   * \"not in cache yet\" (different from `null`, which means \"resolver\n   * ran and the user wasn't found\").\n   */\n  peek(externalId: string): PoolseUserProfile | null | undefined {\n    return this.cache.get(externalId);\n  }\n\n  /**\n   * Resolve a user, hitting the customer's `userResolver` on cache\n   * miss. Concurrent calls for the same external_id share one Promise.\n   */\n  async get(externalId: string): Promise<PoolseUserProfile | null> {\n    if (this.cache.has(externalId)) {\n      return this.cache.get(externalId) ?? null;\n    }\n    const existingPending = this.pending.get(externalId);\n    if (existingPending) return existingPending;\n\n    const resolver = this.config.userResolver;\n    if (!resolver) {\n      this.cache.set(externalId, null);\n      this.notify(externalId);\n      return null;\n    }\n\n    const promise = Promise.resolve()\n      .then(() => resolver(externalId))\n      .then(\n        (profile) => {\n          this.cache.set(externalId, profile ?? null);\n          this.pending.delete(externalId);\n          this.notify(externalId);\n          return profile ?? null;\n        },\n        (err: unknown) => {\n          // Resolver errors are treated as \"user not found\" — log\n          // once and cache the null so we don't hammer the failing\n          // endpoint on every re-render. Customers can call\n          // `invalidate(externalId)` to retry.\n          console.error('[poolse] userResolver failed for', externalId, err);\n          this.cache.set(externalId, null);\n          this.pending.delete(externalId);\n          this.notify(externalId);\n          return null;\n        },\n      );\n    this.pending.set(externalId, promise);\n    return promise;\n  }\n\n  /**\n   * Subscribe to changes for a single external_id. The listener fires\n   * when the resolver lands (or when the entry is invalidated).\n   * Returns an unsubscribe.\n   *\n   * `useUser` in @poolse/react uses this with `useSyncExternalStore`.\n   */\n  subscribe(externalId: string, listener: Listener): () => void {\n    let set = this.listeners.get(externalId);\n    if (!set) {\n      set = new Set();\n      this.listeners.set(externalId, set);\n    }\n    set.add(listener);\n    return () => {\n      set?.delete(listener);\n    };\n  }\n\n  /** Drop a single cached entry — next `get` re-fetches via the resolver. */\n  invalidate(externalId: string): void {\n    this.cache.delete(externalId);\n    this.pending.delete(externalId);\n    this.notify(externalId);\n  }\n\n  /**\n   * Drop the entire cache. Use after a sign-out, tenant swap, or any\n   * other event that invalidates every cached profile (e.g., the\n   * customer just renamed every user in bulk).\n   */\n  invalidateAll(): void {\n    this.cache.clear();\n    this.pending.clear();\n    for (const externalId of this.listeners.keys()) {\n      this.notify(externalId);\n    }\n  }\n\n  private notify(externalId: string): void {\n    const set = this.listeners.get(externalId);\n    if (!set) return;\n    for (const l of set) l();\n  }\n}\n","import { ApiError } from '../errors.js';\nimport type { RestClient } from '../rest-client.js';\nimport type { CallConnection } from '../voice/livekit-types.js';\n\n/**\n * `/v1/conversations/:id/call-token` — SFU credentials for a call.\n *\n * This is the SFU's access control, not a convenience: LiveKit trusts\n * the token completely and checks no membership of its own, so the\n * server mints one only after verifying the caller is in the\n * conversation.\n */\nexport class CallTokensResource {\n  constructor(private readonly client: RestClient) {}\n\n  /**\n   * POST /v1/conversations/:conversationId/call-token\n   *\n   * Resolves `null` when the deployment has no SFU configured (503).\n   * That is deliberately not an error — the caller falls back to the\n   * peer-to-peer mesh, which is how every call worked before the SFU\n   * existed. A 403 still throws: that one really is a refusal.\n   */\n  async create(conversationId: string, signal?: AbortSignal): Promise<CallConnection | null> {\n    try {\n      return await this.client.request<CallConnection>({\n        method: 'POST',\n        path: `/v1/conversations/${encodeURIComponent(conversationId)}/call-token`,\n        ...(signal ? { signal } : {}),\n      });\n    } catch (err) {\n      if (err instanceof ApiError && err.status === 503) return null;\n      throw err;\n    }\n  }\n}\n","import type {\n  CallConnection,\n  CallDevice,\n  CallDeviceKind,\n  CallParticipant,\n  CallRoomOptions,\n  CallRoomStatus,\n  CameraFacing,\n  CheckedLiveKitModule,\n  LiveKitParticipant,\n  LiveKitRoomHandle,\n  LiveKitTrack,\n} from './livekit-types.js';\n\nexport type Unsubscribe = () => void;\n\n/**\n * A call's media, carried by the LiveKit SFU.\n *\n * ## What this is not\n *\n * It is not the call. Ringing, accept/decline/hangup, presence, the\n * roster and mute state all stay on poolse's own channels — see\n * `CallsResource` and `VoiceRoom`. This object owns audio and video\n * packets and nothing else. A client joins both: `voice:conversation:<id>`\n * for who is here and what they are doing, this for what they sound and\n * look like.\n *\n * ## Why an SFU rather than the mesh\n *\n * {@link VoiceRoom} connects every participant to every other one, so\n * each uploads N-1 encoded copies of their own camera. At four people\n * that is roughly 3 Mbps of sustained upload from a phone plus three\n * simultaneous encodes — the handset overheats, iOS throttles, and\n * quality collapses for everyone. Audio survives it because Opus is\n * ~25x cheaper; video does not.\n *\n * The SFU also makes the mid-call camera toggle tractable. Turning a\n * camera on mid-call means renegotiating a live peer connection, which\n * the mesh cannot do — it offers once, on peer discovery. Here it is\n * `setCameraEnabled`.\n *\n * ## Availability\n *\n * A deployment with no SFU configured answers 503, which arrives as\n * `tokenProvider` returning `null`. That is not an error: the caller\n * falls back to the mesh, which is what every call used before this\n * existed. `join()` resolves `false` to say so.\n */\n/**\n * Copy device records into plain objects.\n *\n * Field by field, and that is the whole point. `MediaDeviceInfo` is a\n * WebIDL interface, so `deviceId`, `kind` and `label` are accessors on\n * its PROTOTYPE rather than own enumerable properties — which means\n * `{ ...device }` spreads to `{}` and silently produces a list of\n * devices with no ids and no names. (It is also why the interface\n * carries its own `toJSON`.) Reading each property invokes the getter,\n * which is what actually copies the value.\n *\n * Entries with no `deviceId` are dropped. A browser that has not yet\n * been granted the device returns a placeholder with empty strings, and\n * offering that as a choice gives the user a row that cannot be\n * selected.\n */\nfunction toDevices(\n  raw: readonly { deviceId?: string; kind?: string; label?: string }[],\n  kind: CallDeviceKind,\n): CallDevice[] {\n  const out: CallDevice[] = [];\n  for (const device of raw) {\n    // `getLocalDevices(kind)` has already filtered; `enumerateDevices()`\n    // has not, and returns every kind at once.\n    if (device.kind && device.kind !== kind) continue;\n    const deviceId = device.deviceId ?? '';\n    if (!deviceId) continue;\n    out.push({ deviceId, kind, label: device.label ?? '' });\n  }\n  return out;\n}\n\nexport class CallRoom {\n  private readonly livekit: CheckedLiveKitModule;\n  private readonly tokenProvider: () => Promise<CallConnection | null>;\n  private readonly startWithVideo: boolean;\n  private readonly startMuted: boolean;\n  private readonly aloneGraceMs: number;\n\n  private facing: CameraFacing;\n\n  private room: LiveKitRoomHandle | null = null;\n  private status: CallRoomStatus = 'idle';\n  private selfId: string | null = null;\n\n  // Reference counted like VoiceRoom: a call screen and a roster can\n  // both hold the same call, and the second holder must not open a\n  // second SFU connection or tear the first one down on leaving.\n  private holders = 0;\n\n  /**\n   * Whether anyone else has ever been on this call.\n   *\n   * The whole point of the alone check is to end a call the other side\n   * has vanished from, and \"vanished\" is only meaningful once they were\n   * here. Without this flag the caller who connects first — alone, by\n   * definition, for as long as it takes the callee to join — would end\n   * their own call before it ever started.\n   */\n  private hasSeenPeer = false;\n\n  /** Pending alone verdict, cleared the moment anyone shows up. */\n  private aloneTimer: ReturnType<typeof setTimeout> | null = null;\n\n  private readonly statusListeners = new Set<(status: CallRoomStatus) => void>();\n  private readonly participantListeners = new Set<(participants: CallParticipant[]) => void>();\n  private readonly errorListeners = new Set<(error: Error) => void>();\n  private readonly aloneListeners = new Set<() => void>();\n  private readonly deviceListeners = new Set<() => void>();\n\n  /** Bound once so `off()` in teardown removes the same references. */\n  private readonly onRoomChange = () => this.emitParticipants();\n\n  /**\n   * Hidden `<audio>` elements playing each remote audio track.\n   *\n   * livekit-client does NOT play remote audio for you on the web — that\n   * is what `@livekit/components-react`'s `<RoomAudioRenderer />` exists\n   * to do. Without this a call connects, the roster is right, video\n   * flows, and nobody hears anything. The peer-to-peer mesh always did\n   * this (see `webrtc-browser.ts`); the SFU path has to as well.\n   *\n   * Empty on React Native, where there is no DOM and LiveKit routes\n   * audio through the native audio session instead.\n   */\n  private readonly audioSinks = new Map<LiveKitTrack, HTMLMediaElement>();\n\n  constructor(opts: CallRoomOptions) {\n    // Narrow once, here, rather than making every caller's module match\n    // signature-for-signature — see the note on `LiveKitModule`.\n    this.livekit = opts.livekit as unknown as CheckedLiveKitModule;\n    this.tokenProvider = opts.tokenProvider;\n    this.startWithVideo = opts.video ?? false;\n    this.startMuted = opts.muted ?? false;\n    this.facing = opts.facing ?? 'user';\n    this.aloneGraceMs = opts.aloneGraceMs ?? 1500;\n  }\n\n  // ── observation ─────────────────────────────────────────────────────\n\n  getStatus(): CallRoomStatus {\n    return this.status;\n  }\n\n  onStatus(fn: (status: CallRoomStatus) => void): Unsubscribe {\n    this.statusListeners.add(fn);\n    return () => this.statusListeners.delete(fn);\n  }\n\n  onParticipants(fn: (participants: CallParticipant[]) => void): Unsubscribe {\n    this.participantListeners.add(fn);\n    return () => this.participantListeners.delete(fn);\n  }\n\n  onError(fn: (error: Error) => void): Unsubscribe {\n    this.errorListeners.add(fn);\n    return () => this.errorListeners.delete(fn);\n  }\n\n  /**\n   * Everyone else has left and is not coming back.\n   *\n   * A call whose other participants hang up cleanly ends by signal:\n   * `call:hangup` travels over poolse's own channel and the far side\n   * closes its screen. This covers the case where no signal is ever\n   * sent — the app was killed, the phone lost its network, the tab was\n   * closed — where the only evidence is that the SFU roster emptied.\n   *\n   * Media is NOT torn down here. Whoever handles this owns hanging up,\n   * because ending a call also means telling poolse about it, which is\n   * a layer this class deliberately knows nothing about.\n   */\n  onAlone(fn: () => void): Unsubscribe {\n    this.aloneListeners.add(fn);\n    return () => this.aloneListeners.delete(fn);\n  }\n\n  getParticipants(): CallParticipant[] {\n    if (!this.room) return [];\n\n    const self = this.toParticipant(this.room.localParticipant, true);\n    const others = [...this.room.remoteParticipants.values()].map((p) =>\n      this.toParticipant(p, false),\n    );\n\n    return [self, ...others];\n  }\n\n  // ── lifecycle ───────────────────────────────────────────────────────\n\n  /**\n   * Connect to the SFU.\n   *\n   * Resolves `true` once media is flowing, `false` when the deployment\n   * has no SFU — the caller should fall back to the mesh rather than\n   * treat that as a failed call.\n   */\n  async join(): Promise<boolean> {\n    if (this.room) {\n      this.holders += 1;\n      return true;\n    }\n\n    this.holders += 1;\n    this.setStatus('connecting');\n\n    let connection: CallConnection | null;\n    try {\n      connection = await this.tokenProvider();\n    } catch (err) {\n      this.holders = Math.max(0, this.holders - 1);\n      this.setStatus('error');\n      const error = new Error(`call token unavailable: ${String(err)}`);\n      this.emitError(error);\n      throw error;\n    }\n\n    if (!connection) {\n      // No SFU configured. Not an error, and deliberately distinguishable\n      // from one so the caller can fall back instead of telling the user\n      // their call failed.\n      this.holders = Math.max(0, this.holders - 1);\n      this.setStatus('idle');\n      return false;\n    }\n\n    const room = new this.livekit.Room({\n      // Let LiveKit drop video layers before it drops the call. On a\n      // phone leaving wifi this is the difference between the picture\n      // degrading and the call ending.\n      adaptiveStream: true,\n      dynacast: true,\n    });\n    this.room = room;\n    this.bind(room);\n\n    try {\n      await room.connect(connection.url, connection.token);\n      this.selfId = room.localParticipant.identity;\n\n      // Publish AFTER connecting: publishing first would acquire the\n      // camera and microphone before we know the room will accept us,\n      // leaving the capture indicator lit on a call that never happened.\n      //\n      // Neither of these may fail the call. A desktop with no webcam\n      // throws `NotFoundError` from `setCameraEnabled`, and that used to\n      // land in the catch below and tear the whole call down — a video\n      // call was simply impossible on any machine without a camera,\n      // when it should have connected as audio. The same reasoning\n      // applies to a missing or refused microphone: being able to hear\n      // the other side beats not connecting at all.\n      //\n      // Both report through `onError`, so the UI can say which half is\n      // missing rather than leaving the user guessing.\n      await this.publish(\n        () => room.localParticipant.setMicrophoneEnabled(!this.startMuted),\n        'microphone',\n      );\n      if (this.startWithVideo) {\n        await this.publish(\n          () => room.localParticipant.setCameraEnabled(true, { facingMode: this.facing }),\n          'camera',\n        );\n      }\n\n      // Browsers keep audio silent until the page has seen a user\n      // gesture. Answering a call is one, so this normally resolves\n      // immediately — but if it doesn't, a call that connects and plays\n      // nothing is indistinguishable from a broken one.\n      try {\n        await room.startAudio?.();\n      } catch {\n        // Still blocked. The next tap anywhere in the app releases it,\n        // and failing the whole call over it would be far worse.\n      }\n\n      this.setStatus('connected');\n      this.emitParticipants();\n      return true;\n    } catch (err) {\n      this.holders = Math.max(0, this.holders - 1);\n      this.setStatus('error');\n      const error = new Error(`call media failed: ${String(err)}`);\n      this.emitError(error);\n      await this.teardown();\n      throw error;\n    }\n  }\n\n  /** Release one holder; disconnects once none are left. */\n  leave(): void {\n    this.holders = Math.max(0, this.holders - 1);\n    if (this.holders > 0) return;\n    void this.teardown();\n  }\n\n  // ── media controls ──────────────────────────────────────────────────\n\n  /**\n   * Turn the camera on or off mid-call.\n   *\n   * Off genuinely stops publishing rather than sending black frames, so\n   * the capture indicator goes out and the uplink is freed. LiveKit\n   * renegotiates underneath.\n   */\n  async setCameraEnabled(enabled: boolean): Promise<void> {\n    await this.withLocal(\n      (local) =>\n        enabled\n          ? local.setCameraEnabled(true, { facingMode: this.facing })\n          : local.setCameraEnabled(false),\n      'camera',\n    );\n  }\n\n  /**\n   * Swap between the front and rear cameras.\n   *\n   * `restartTrack` re-acquires the capture device under the *existing*\n   * publication, so the far side's tile keeps rendering throughout.\n   * Unpublishing and republishing instead would blank their view and\n   * force a renegotiation for what is, to them, the same camera.\n   *\n   * No-ops when the camera is off — there is nothing to restart, and\n   * the next `setCameraEnabled(true)` will open whichever lens is\n   * selected anyway.\n   */\n  async switchCamera(): Promise<void> {\n    const room = this.room;\n    if (!room) return;\n\n    const source = this.livekit.Track.Source['Camera'] ?? 'camera';\n    const track = room.localParticipant.getTrackPublication(source)?.videoTrack;\n    if (!track?.restartTrack) return;\n\n    const next: CameraFacing = this.facing === 'user' ? 'environment' : 'user';\n    try {\n      await track.restartTrack({ facingMode: next });\n      this.facing = next;\n      this.emitParticipants();\n    } catch (err) {\n      // A device with one camera, or one that refuses the swap. The\n      // call carries on pointed wherever it already was.\n      this.emitError(new Error(`could not switch camera: ${String(err)}`));\n    }\n  }\n\n  /** Which camera the local video track is capturing from. */\n  getFacingMode(): CameraFacing {\n    return this.facing;\n  }\n\n  // ── device selection ────────────────────────────────────────────────\n\n  /**\n   * Every device of a given kind that could carry this call.\n   *\n   * The web's equivalent of a phone's speaker button: a laptop has no\n   * earpiece to switch to, but it does have three microphones and a\n   * pair of headphones, and picking between them is the same job.\n   *\n   * Prefers livekit-client's own enumeration, which prompts for the\n   * permission that makes labels visible, and falls back to the plain\n   * browser API so a module without the static still lists something.\n   */\n  async listDevices(kind: CallDeviceKind): Promise<CallDevice[]> {\n    try {\n      const fromLiveKit = await this.livekit.Room.getLocalDevices?.(kind, false);\n      if (fromLiveKit?.length) return toDevices(fromLiveKit, kind);\n    } catch {\n      // Fall through — a refused enumeration should cost the picker,\n      // not the call.\n    }\n\n    const media = globalThis.navigator?.mediaDevices;\n    if (!media?.enumerateDevices) return [];\n\n    try {\n      return toDevices(await media.enumerateDevices(), kind);\n    } catch {\n      return [];\n    }\n  }\n\n  /** Which device of `kind` the call is currently using. */\n  getActiveDevice(kind: CallDeviceKind): string | undefined {\n    return this.room?.getActiveDevice?.(kind);\n  }\n\n  /**\n   * Move the call onto another device.\n   *\n   * `audiooutput` re-points playback through `setSinkId`, which some\n   * browsers do not implement — hence the boolean rather than a throw.\n   * A refusal is reported as an error and leaves the call where it was.\n   */\n  async setActiveDevice(kind: CallDeviceKind, deviceId: string): Promise<void> {\n    const room = this.room;\n    if (!room?.switchActiveDevice) return;\n\n    try {\n      await room.switchActiveDevice(kind, deviceId);\n      this.emitParticipants();\n    } catch (err) {\n      this.emitError(new Error(`could not switch ${kind}: ${String(err)}`));\n    }\n  }\n\n  /** Fires when devices are plugged in or removed. */\n  onDevices(fn: () => void): Unsubscribe {\n    this.deviceListeners.add(fn);\n    return () => this.deviceListeners.delete(fn);\n  }\n\n  /** Mute or unmute the microphone. */\n  async setMicrophoneEnabled(enabled: boolean): Promise<void> {\n    await this.withLocal((local) => local.setMicrophoneEnabled(enabled), 'microphone');\n  }\n\n  isCameraEnabled(): boolean {\n    return this.room?.localParticipant.isCameraEnabled ?? false;\n  }\n\n  isMicrophoneEnabled(): boolean {\n    return this.room?.localParticipant.isMicrophoneEnabled ?? false;\n  }\n\n  // ── internals ───────────────────────────────────────────────────────\n\n  /**\n   * Publish one capture device, surviving its absence.\n   *\n   * Split out from {@link withLocal} because this runs mid-join, before\n   * the room is marked connected — emitting a roster here would\n   * advertise a call that has not finished starting.\n   */\n  private async publish(fn: () => Promise<unknown>, what: string): Promise<void> {\n    try {\n      await fn();\n    } catch (err) {\n      this.emitError(new Error(`no ${what} available: ${String(err)}`));\n    }\n  }\n\n  private async withLocal(\n    fn: (local: LiveKitRoomHandle['localParticipant']) => Promise<unknown>,\n    what: string,\n  ): Promise<void> {\n    const room = this.room;\n    if (!room) return;\n\n    try {\n      await fn(room.localParticipant);\n      this.emitParticipants();\n    } catch (err) {\n      // A refused camera must not end the call — the user can carry on\n      // talking, and the roster will show their camera as off.\n      this.emitError(new Error(`could not change ${what}: ${String(err)}`));\n    }\n  }\n\n  private bind(room: LiveKitRoomHandle): void {\n    const { RoomEvent } = this.livekit;\n\n    // Every one of these changes what the roster should show. Rather\n    // than diffing, each re-reads the room — the participant count in a\n    // call is small, and a wrong roster is worse than a cheap rebuild.\n    for (const event of [\n      RoomEvent['ParticipantConnected'],\n      RoomEvent['ParticipantDisconnected'],\n      RoomEvent['TrackSubscribed'],\n      RoomEvent['TrackUnsubscribed'],\n      RoomEvent['TrackMuted'],\n      RoomEvent['TrackUnmuted'],\n      RoomEvent['LocalTrackPublished'],\n      RoomEvent['LocalTrackUnpublished'],\n      RoomEvent['ActiveSpeakersChanged'],\n      RoomEvent['ParticipantNameChanged'],\n    ]) {\n      if (event) room.on(event, this.onRoomChange);\n    }\n\n    // Remote audio playback. Separate from the roster handlers above\n    // because these need the track itself, not just a nudge to re-read\n    // the room.\n    const subscribed = RoomEvent['TrackSubscribed'];\n    if (subscribed) {\n      room.on(subscribed, ((track: LiveKitTrack) => this.playAudio(track)) as never);\n    }\n\n    const unsubscribed = RoomEvent['TrackUnsubscribed'];\n    if (unsubscribed) {\n      room.on(unsubscribed, ((track: LiveKitTrack) => this.stopAudio(track)) as never);\n    }\n\n    // Headphones plugged in, a webcam unplugged. The picker has to\n    // re-read rather than show a device that is no longer there.\n    const devicesChanged = RoomEvent['MediaDevicesChanged'];\n    if (devicesChanged) {\n      room.on(devicesChanged, () => {\n        for (const fn of this.deviceListeners) fn();\n      });\n    }\n\n    const disconnected = RoomEvent['Disconnected'];\n    if (disconnected) {\n      room.on(disconnected, () => {\n        // The SFU dropped us. Reflect it rather than showing a call that\n        // looks live and carries nothing.\n        this.setStatus('idle');\n        this.emitParticipants();\n      });\n    }\n  }\n\n  /**\n   * Play a remote audio track through a hidden element.\n   *\n   * No-ops for video (the UI renders that) and on React Native, where\n   * there is no `document` and the native audio session handles\n   * playback.\n   */\n  private playAudio(track: LiveKitTrack): void {\n    if (typeof document === 'undefined') return;\n    if (track?.kind !== 'audio' || typeof track.attach !== 'function') return;\n    if (this.audioSinks.has(track)) return;\n\n    try {\n      const element = track.attach();\n      element.autoplay = true;\n      // In the DOM (required for playback) but never laid out.\n      element.style.display = 'none';\n      document.body.appendChild(element);\n      this.audioSinks.set(track, element);\n    } catch (err) {\n      this.emitError(new Error(`could not play remote audio: ${String(err)}`));\n    }\n  }\n\n  /** Tear a sink down, so a departed peer stops holding an element. */\n  private stopAudio(track: LiveKitTrack): void {\n    const element = this.audioSinks.get(track);\n    if (!element) return;\n\n    this.audioSinks.delete(track);\n    try {\n      track.detach?.(element);\n    } catch {\n      // Already detached by LiveKit; removing the element is what counts.\n    }\n    element.remove();\n  }\n\n  private toParticipant(participant: LiveKitParticipant, isSelf: boolean): CallParticipant {\n    const cameraSource = this.livekit.Track.Source['Camera'] ?? 'camera';\n    const publication = participant.getTrackPublication(cameraSource);\n\n    // A publication with a muted or absent track is a camera that is\n    // off. Handing back the track anyway would render a frozen last\n    // frame, which reads as a stalled call.\n    const live = publication && !publication.isMuted && publication.track ? publication : null;\n    const videoTrack: LiveKitTrack | null = live?.track ?? null;\n\n    return {\n      userId: participant.identity,\n      name: participant.name,\n      isSelf,\n      micEnabled: participant.isMicrophoneEnabled ?? false,\n      cameraEnabled: participant.isCameraEnabled ?? false,\n      speaking: participant.isSpeaking ?? false,\n      videoTrack,\n      videoTrackRef: live ? { participant, publication: live, source: cameraSource } : null,\n    };\n  }\n\n  private async teardown(): Promise<void> {\n    const room = this.room;\n    this.room = null;\n    this.selfId = null;\n    this.holders = 0;\n\n    // Reset, not preserved: this object can be joined again, and a\n    // stale `hasSeenPeer` would let the next call end itself while the\n    // callee was still picking up.\n    this.hasSeenPeer = false;\n    this.clearAloneTimer();\n\n    for (const track of [...this.audioSinks.keys()]) this.stopAudio(track);\n\n    if (room) {\n      try {\n        await room.disconnect();\n      } catch {\n        // Already gone. Disconnecting twice is not an error worth\n        // surfacing to a user who has already hung up.\n      }\n    }\n\n    this.setStatus('idle');\n    this.emitParticipants();\n  }\n\n  private setStatus(status: CallRoomStatus): void {\n    if (this.status === status) return;\n    this.status = status;\n    for (const fn of this.statusListeners) fn(status);\n  }\n\n  private emitParticipants(): void {\n    const participants = this.getParticipants();\n    for (const fn of this.participantListeners) fn(participants);\n    this.checkAlone();\n  }\n\n  /**\n   * Decide whether this client is the last one standing.\n   *\n   * Runs on every roster change. Three things have to be true before a\n   * call is declared over: it is actually connected, somebody else was\n   * here at some point, and nobody is here now — and even then the\n   * verdict waits out {@link CallRoomOptions.aloneGraceMs}, so a\n   * simultaneous hang-up or a momentary SFU reconnect does not read as\n   * abandonment.\n   */\n  private checkAlone(): void {\n    if (this.aloneGraceMs <= 0) return;\n\n    const others = this.room?.remoteParticipants.size ?? 0;\n\n    if (others > 0) {\n      this.hasSeenPeer = true;\n      this.clearAloneTimer();\n      return;\n    }\n\n    // Alone, but never had company: this is the caller waiting for an\n    // answer, not a call anyone walked out of.\n    if (!this.hasSeenPeer || this.status !== 'connected') return;\n    if (this.aloneTimer) return;\n\n    this.aloneTimer = setTimeout(() => {\n      this.aloneTimer = null;\n      // Re-check rather than trusting the reading that armed the timer:\n      // someone may have rejoined during the grace period, and the\n      // roster is the authority, not the schedule.\n      if ((this.room?.remoteParticipants.size ?? 0) > 0) return;\n      if (this.status !== 'connected') return;\n      for (const fn of this.aloneListeners) fn();\n    }, this.aloneGraceMs);\n  }\n\n  private clearAloneTimer(): void {\n    if (!this.aloneTimer) return;\n    clearTimeout(this.aloneTimer);\n    this.aloneTimer = null;\n  }\n\n  private emitError(error: Error): void {\n    for (const fn of this.errorListeners) fn(error);\n  }\n\n  /** The local participant's poolse user id, once connected. */\n  getSelfId(): string | null {\n    return this.selfId;\n  }\n}\n","import type { RestClient } from '../rest-client.js';\nimport type { VoiceIceServer } from '../voice/types.js';\n\nexport interface IceServerResponse {\n  ice_servers: VoiceIceServer[];\n  ttl_seconds: number;\n}\n\n/**\n * `/v1/ice-servers` — STUN, and TURN when the deployment has it.\n *\n * Fetched rather than configured because TURN credentials are\n * deliberately short-lived. A client that held a static one could not\n * refresh it, and a TURN password compiled into a mobile binary is\n * extractable by anyone who wants it.\n */\nexport class IceServersResource {\n  constructor(private readonly client: RestClient) {}\n\n  /** GET /v1/ice-servers */\n  list(signal?: AbortSignal): Promise<IceServerResponse> {\n    return this.client.request<IceServerResponse>({\n      method: 'GET',\n      path: '/v1/ice-servers',\n      ...(signal ? { signal } : {}),\n    });\n  }\n}\n","// Low-level fetch wrapper.\n//\n// Responsibilities:\n//   * Apply the Bearer JWT from `config.getToken()`.\n//   * Auto-generate an `Idempotency-Key` for non-GET requests so poolse\n//     can dedupe retries safely.\n//   * Retry on transient failures: network errors, 5xx, 429.\n//     - Backoff = max(Retry-After header, exponential with jitter).\n//     - 401/4xx-other are NOT retried (they won't change on repeat).\n//   * Translate non-2xx into typed `ApiError` subclasses.\n\nimport type { ResolvedConfig } from './config.js';\nimport { ApiError, AuthError, NetworkError, RateLimitedError } from './errors.js';\nimport type { TokenCache } from './token-cache.js';\nimport type { ErrorEnvelope } from './types.js';\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';\n\nexport interface RequestOptions {\n  method: HttpMethod;\n  path: string;\n  /** JSON-serialisable body for non-GETs. Omit for GET/DELETE. */\n  body?: unknown;\n  /** Query string params; values are stringified, nullish entries dropped. */\n  query?: Record<string, string | number | boolean | null | undefined>;\n  /**\n   * Idempotency-Key override. Defaults to a fresh UUID for non-GETs.\n   * Pass `null` to deliberately omit the header (e.g. when the caller's\n   * own retry logic supplies a deterministic one).\n   */\n  idempotencyKey?: string | null;\n  /**\n   * Per-request override for total retry budget. Defaults to\n   * `config.maxRetries`.\n   */\n  maxRetries?: number;\n  /** AbortSignal for caller-driven cancellation. */\n  signal?: AbortSignal;\n}\n\nconst NON_BODY_METHODS: ReadonlySet<HttpMethod> = new Set(['GET', 'DELETE']);\nconst IDEMPOTENT_METHODS: ReadonlySet<HttpMethod> = new Set(['GET']);\n\nexport class RestClient {\n  private readonly config: ResolvedConfig;\n  private readonly tokenCache: TokenCache;\n\n  constructor(config: ResolvedConfig, tokenCache: TokenCache) {\n    this.config = config;\n    this.tokenCache = tokenCache;\n  }\n\n  async request<T>(opts: RequestOptions): Promise<T> {\n    const url = this.buildUrl(opts.path, opts.query);\n    const maxRetries = opts.maxRetries ?? this.config.maxRetries;\n    const idempotencyKey = this.resolveIdempotencyKey(opts);\n\n    let attempt = 0;\n    let triedAuthRefresh = false;\n\n    // The retry loop runs up to `maxRetries + 1` total attempts. Each\n    // failed attempt either returns (giving up) or waits per the backoff.\n    for (;;) {\n      const body = opts.body === undefined ? undefined : JSON.stringify(opts.body);\n      const headers = await this.buildHeaders(opts.method, idempotencyKey, body !== undefined);\n\n      let response: Response;\n      try {\n        const init: RequestInit = { method: opts.method, headers };\n        if (body !== undefined) init.body = body;\n        if (opts.signal) init.signal = opts.signal;\n        response = await this.config.fetch(url, init);\n      } catch (err) {\n        // AbortError is caller intent (component unmount, conv switch,\n        // StrictMode double-effect). Re-throw AS-IS so callers can\n        // distinguish it from a real network failure. Wrapping it as\n        // NetworkError previously caused hooks like useMembers to fall\n        // into their \"failed to load\" branch whenever the aborted fetch\n        // resolved after a newly-mounted fetcher already cleared state.\n        if (err instanceof DOMException && err.name === 'AbortError') {\n          throw err;\n        }\n        if (attempt < maxRetries && isRetryableNetworkError(err)) {\n          await sleep(this.backoffDelay(attempt));\n          attempt += 1;\n          continue;\n        }\n        throw new NetworkError('Network request failed', err);\n      }\n\n      if (response.status >= 200 && response.status < 300) {\n        return (await parseJsonOrNull(response)) as T;\n      }\n\n      // 401: a cached token can race a clock-skew expiry or a server\n      // restart. Invalidate the token cache and retry ONCE — if the\n      // refreshed token also gets 401, the credentials are genuinely\n      // bad and we surface it. Doesn't count against the per-request\n      // retry budget (auth refresh isn't a \"transient\" failure in the\n      // same sense as 5xx/network).\n      if (response.status === 401) {\n        if (!triedAuthRefresh) {\n          this.tokenCache.invalidate();\n          triedAuthRefresh = true;\n          continue;\n        }\n        throw new AuthError(await parseEnvelope(response));\n      }\n\n      // 429: retry after the larger of (Retry-After, exponential backoff).\n      if (response.status === 429) {\n        const envelope = await parseEnvelope(response);\n        const retryAfterMs = retryAfterHeaderMs(response);\n        if (attempt < maxRetries) {\n          await sleep(Math.max(retryAfterMs ?? 0, this.backoffDelay(attempt)));\n          attempt += 1;\n          continue;\n        }\n        throw new RateLimitedError(envelope, retryAfterMs ?? 0);\n      }\n\n      // 5xx: retry if we have budget and the method is safe to retry.\n      // Non-idempotent methods (POST/PATCH/PUT/DELETE) are STILL retried\n      // here because the Idempotency-Key header makes duplicates safe.\n      if (response.status >= 500 && attempt < maxRetries) {\n        await sleep(this.backoffDelay(attempt));\n        attempt += 1;\n        continue;\n      }\n\n      throw new ApiError(response.status, await parseEnvelope(response));\n    }\n  }\n\n  // ── helpers ────────────────────────────────────────────────────────────\n\n  private buildUrl(path: string, query?: RequestOptions['query']): string {\n    const base = `${this.config.apiUrl}${path.startsWith('/') ? path : `/${path}`}`;\n    if (!query) return base;\n\n    const params = new URLSearchParams();\n    for (const [k, v] of Object.entries(query)) {\n      if (v !== undefined && v !== null) {\n        params.append(k, String(v));\n      }\n    }\n    const qs = params.toString();\n    return qs ? `${base}?${qs}` : base;\n  }\n\n  private async buildHeaders(\n    method: HttpMethod,\n    idempotencyKey: string | null,\n    hasBody: boolean,\n  ): Promise<Record<string, string>> {\n    const headers: Record<string, string> = { Accept: 'application/json' };\n\n    if (hasBody) headers['Content-Type'] = 'application/json';\n\n    const token = await this.config.getToken();\n    if (token) headers['Authorization'] = `Bearer ${token}`;\n\n    if (!IDEMPOTENT_METHODS.has(method) && idempotencyKey) {\n      headers['Idempotency-Key'] = idempotencyKey;\n    }\n\n    return headers;\n  }\n\n  private resolveIdempotencyKey(opts: RequestOptions): string | null {\n    if (opts.idempotencyKey === null) return null;\n    if (opts.idempotencyKey) return opts.idempotencyKey;\n    if (IDEMPOTENT_METHODS.has(opts.method)) return null;\n    return this.config.generateIdempotencyKey();\n  }\n\n  private backoffDelay(attempt: number): number {\n    const exp = this.config.baseBackoffMs * 2 ** attempt;\n    const capped = Math.min(this.config.maxBackoffMs, exp);\n    // Full jitter: pick uniformly in [0, capped]. Avoids retry-storm\n    // synchronization when many clients fail at once.\n    return Math.floor(Math.random() * capped);\n  }\n}\n\nfunction _unusedNonBodyMethods(): unknown {\n  return NON_BODY_METHODS;\n}\n\nasync function parseEnvelope(response: Response): Promise<ErrorEnvelope['error']> {\n  try {\n    const json = (await response.json()) as ErrorEnvelope;\n    if (json?.error?.code) return json.error;\n  } catch {\n    // fall through to a synthetic envelope below\n  }\n  return {\n    code: 'unknown_error',\n    message: `HTTP ${response.status}`,\n    doc_url: '',\n  };\n}\n\nasync function parseJsonOrNull(response: Response): Promise<unknown> {\n  if (response.status === 204) return null;\n  const text = await response.text();\n  if (!text) return null;\n  return JSON.parse(text);\n}\n\nfunction retryAfterHeaderMs(response: Response): number | null {\n  const raw = response.headers.get('retry-after');\n  if (!raw) return null;\n  const seconds = Number.parseInt(raw, 10);\n  return Number.isFinite(seconds) ? seconds * 1000 : null;\n}\n\nfunction isRetryableNetworkError(err: unknown): boolean {\n  // Abort is caller intent — never retry.\n  if (err instanceof DOMException && err.name === 'AbortError') return false;\n  // Everything else (TypeError from fetch failure, etc.) is fair game.\n  return true;\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// Caches the JWT returned by the consumer's `getToken` callback so the\n// SDK doesn't call back on every REST request and every WebSocket\n// connect. Without this, mounting a single conversation view fires\n// ~4-5 `getToken` calls per render — and every parent re-render that\n// (accidentally) hands the provider a new config object multiplies\n// that out, turning a passive UI into a token-fetch storm.\n//\n// The cache:\n//   * Decodes the `exp` claim (no signature verification — that's the\n//     server's job) and returns the cached token until `exp - 30s`.\n//   * Coalesces concurrent calls: if a refresh is in flight, every\n//     caller awaits the same promise — one network round-trip even\n//     when 4 hooks mount simultaneously.\n//   * Can be `invalidate()`-d from the outside (e.g. by the REST client\n//     after a 401) so the next call always re-fetches.\n//   * Treats opaque (non-JWT) tokens as cacheable for `FALLBACK_TTL_MS`\n//     — long enough to absorb a mount burst, short enough that opaque\n//     rotations still land within a few seconds.\n//   * NEVER caches `null` (an unauthenticated request is a choice the\n//     consumer makes per call, not a state to memoise).\n\nimport type { PoolseConfig } from './config.js';\n\ntype Fetcher = PoolseConfig['getToken'];\n\ninterface GetTokenOptions {\n  /** Bypass the cache and force a fresh call to the consumer's `getToken`. */\n  forceRefresh?: boolean;\n}\n\nconst REFRESH_BUFFER_MS = 30_000;\nconst FALLBACK_TTL_MS = 60_000;\n\nexport class TokenCache {\n  private token: string | null = null;\n  private expMs: number | null = null;\n  private inFlight: Promise<string | null> | null = null;\n\n  constructor(private readonly fetcher: Fetcher) {}\n\n  /**\n   * Synchronously return the cached token without triggering a fetch.\n   * Returns `null` if the cache is empty OR if the cached token is\n   * within the refresh window (treating near-expiry tokens as stale\n   * keeps the realtime layer from handshaking with an about-to-expire\n   * JWT when a refresh is already due).\n   *\n   * Exists for callers like Phoenix.js's `params` callback that the\n   * library invokes synchronously and does NOT await — see\n   * `phoenix/priv/static/phoenix.mjs::endPointURL()`.\n   */\n  peekToken(): string | null {\n    if (this.token === null || this.expMs === null) return this.token;\n    return Date.now() < this.expMs - REFRESH_BUFFER_MS ? this.token : null;\n  }\n\n  async getToken(opts: GetTokenOptions = {}): Promise<string | null> {\n    if (opts.forceRefresh) this.invalidate();\n\n    const now = Date.now();\n    if (this.token && this.expMs !== null && now < this.expMs - REFRESH_BUFFER_MS) {\n      return this.token;\n    }\n\n    if (this.inFlight) return this.inFlight;\n\n    this.inFlight = this.fetchAndStore().finally(() => {\n      this.inFlight = null;\n    });\n    return this.inFlight;\n  }\n\n  invalidate(): void {\n    this.token = null;\n    this.expMs = null;\n    // Don't clear `inFlight` — let the existing fetch resolve normally;\n    // its result just won't be cached (the freshness check above will\n    // miss it). The next call after `invalidate()` will be served by\n    // that same in-flight promise if it's still pending.\n  }\n\n  private async fetchAndStore(): Promise<string | null> {\n    const token = await this.fetcher();\n    if (!token) {\n      this.token = null;\n      this.expMs = null;\n      return null;\n    }\n\n    const expSec = parseJwtExp(token);\n    if (expSec !== null) {\n      const expMs = expSec * 1000;\n      // Already expired by the time it reached us — cache for a short\n      // fallback so the burst doesn't hammer, but don't trust the exp.\n      // The next REST 401 will invalidate and we'll re-fetch.\n      this.expMs = expMs <= Date.now() ? Date.now() + FALLBACK_TTL_MS : expMs;\n    } else {\n      this.expMs = Date.now() + FALLBACK_TTL_MS;\n    }\n    this.token = token;\n    return token;\n  }\n}\n\n// JWT payload base64url-decode → JSON parse → pluck `exp`. Returns\n// null if the token isn't a JWT, the payload is unreadable, or `exp`\n// is missing/non-numeric. Never throws — bad tokens just go uncached.\nfunction parseJwtExp(token: string): number | null {\n  const parts = token.split('.');\n  if (parts.length !== 3) return null;\n\n  try {\n    const json = decodeBase64Url(parts[1] as string);\n    const payload = JSON.parse(json) as { exp?: unknown };\n    return typeof payload.exp === 'number' && Number.isFinite(payload.exp) ? payload.exp : null;\n  } catch {\n    return null;\n  }\n}\n\nfunction decodeBase64Url(s: string): string {\n  // JWT uses base64url (RFC 7515 §2): `-` and `_` instead of `+` and\n  // `/`, no padding. Translate back to standard base64 and re-pad.\n  const b64 = s.replace(/-/g, '+').replace(/_/g, '/');\n  const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);\n  if (typeof atob === 'function') return atob(padded);\n  // Node fallback (older runtimes without global atob). The SDK's\n  // minimum target is Node 18 where atob is global, but keep this for\n  // safety / SSR environments that polyfill differently.\n  const g = globalThis as {\n    Buffer?: { from(s: string, e: string): { toString(e: string): string } };\n  };\n  if (g.Buffer) return g.Buffer.from(padded, 'base64').toString('binary');\n  throw new Error('No base64 decoder available');\n}\n","// Public entry-point for the SDK. One instance per End User session.\n// Re-create when the user signs out or rotates tenants.\n\nimport type { PoolseConfig, ResolvedConfig } from './config.js';\nimport { resolveConfig } from './config.js';\nimport { PoolseRealtime } from './realtime/realtime.js';\nimport { AttachmentsResource } from './resources/attachments.js';\nimport { ConversationsResource } from './resources/conversations.js';\nimport { DevicesResource } from './resources/devices.js';\nimport { MeResource } from './resources/me.js';\nimport { MessagesResource } from './resources/messages.js';\nimport { UsersResource } from './resources/users.js';\nimport { CallTokensResource } from './resources/call-tokens.js';\nimport { CallRoom } from './voice/call-room.js';\nimport type { CallRoomOptions } from './voice/livekit-types.js';\nimport { IceServersResource } from './resources/ice-servers.js';\nimport { RestClient } from './rest-client.js';\nimport { TokenCache } from './token-cache.js';\n\nexport class Poolse {\n  /** `/v1/me` — current End User. */\n  public readonly me: MeResource;\n\n  /**\n   * `/v1/devices` — push destinations, so an incoming call can ring a\n   * phone whose app isn't running. Only meaningful on mobile.\n   */\n  public readonly devices: DevicesResource;\n  /** `/v1/conversations` collection + per-conversation handle factory. */\n  public readonly conversations: ConversationsResource;\n  /** `/v1/messages/:id/*` — accessed via `chat.messages.one(id)`. */\n  public readonly messages: MessagesResource;\n  /** `/v1/attachments/*` — presigned-URL uploads/downloads. */\n  public readonly attachments: AttachmentsResource;\n\n  /**\n   * Customer-supplied user metadata, cached + dedup'd.\n   * `chat.users.get(userId)` returns `{ displayName, avatarUrl }`\n   * via the optional `config.userResolver`. UI components\n   * (`MessageBubble`, `MemberList`, `TypingIndicator`) pick this up\n   * automatically via the `useUser` hook in `@poolse/react`.\n   *\n   * If no resolver is configured, `get` always returns `null` and\n   * UI falls back to the userId slice + initials avatar.\n   */\n  public readonly users: UsersResource;\n\n  /**\n   * Low-level REST client. Exposed for advanced use cases (custom endpoints,\n   * raw retry/headers control). Most callers should use the resources above.\n   */\n  public readonly rest: RestClient;\n\n  /**\n   * WebSocket / Phoenix Channels client. Lazily connects on the first\n   * `poolse.realtime.conversation(id)` / `poolse.realtime.user(id)`\n   * call — passing `config.apiUrl` (with `http(s)://` swapped to\n   * `ws(s)://`) for the socket URL by default, overridable via\n   * `config.wsUrl`.\n   */\n  public readonly realtime: PoolseRealtime;\n  /** STUN/TURN servers for WebRTC — see `IceServersResource`. */\n  public readonly iceServers: IceServersResource;\n  /** SFU credentials for a call's media — see `CallTokensResource`. */\n  public readonly callTokens: CallTokensResource;\n\n  private readonly resolved: ResolvedConfig;\n  private readonly tokenCache: TokenCache;\n\n  constructor(config: PoolseConfig) {\n    this.resolved = resolveConfig(config);\n\n    // Wrap the consumer's `getToken` in a cache so the SDK doesn't\n    // call back on every REST request / WebSocket connect. Both the\n    // REST client and the realtime layer share this one instance so a\n    // freshly-minted token from one path serves all subsequent calls.\n    this.tokenCache = new TokenCache(this.resolved.getToken);\n    const cachedConfig: ResolvedConfig = {\n      ...this.resolved,\n      getToken: () => this.tokenCache.getToken(),\n    };\n\n    this.rest = new RestClient(cachedConfig, this.tokenCache);\n    this.me = new MeResource(this.rest);\n    this.devices = new DevicesResource(this.rest);\n    this.conversations = new ConversationsResource(this.rest);\n    this.messages = new MessagesResource(this.rest);\n    this.attachments = new AttachmentsResource(this.rest, cachedConfig.fetch);\n    this.users = new UsersResource(cachedConfig);\n    this.iceServers = new IceServersResource(this.rest);\n    this.callTokens = new CallTokensResource(this.rest);\n\n    this.realtime = new PoolseRealtime(cachedConfig, this.tokenCache, {\n      ...(this.resolved.wsUrl !== undefined ? { wsUrl: this.resolved.wsUrl } : {}),\n      socketPath: this.resolved.socketPath,\n      // Re-fetched on every room join rather than cached here: TURN\n      // credentials expire, and a stale one is rejected silently — the\n      // call connects and carries no media.\n      iceServersProvider: async () => (await this.iceServers.list()).ice_servers,\n    });\n  }\n\n  /**\n   * A call's media, carried by the SFU.\n   *\n   * Media only — ringing, presence, roster and mute state stay on\n   * poolse's own channels, and a client joins both. See {@link CallRoom}.\n   *\n   * `livekit` is your app's `livekit-client` import. This package cannot\n   * import it for you: tsup rewrites `require()` into `__require()`,\n   * which Metro cannot follow, so a dependency required from in here is\n   * absent from every React Native bundle.\n   *\n   *     import * as livekit from 'livekit-client';\n   *     const call = poolse.call(conversationId, { livekit, video: true });\n   *     const usingSfu = await call.join();   // false = no SFU, use the mesh\n   */\n  call(\n    conversationId: string,\n    opts: Omit<CallRoomOptions, 'tokenProvider'> & Partial<Pick<CallRoomOptions, 'tokenProvider'>>,\n  ): CallRoom {\n    return new CallRoom({\n      ...opts,\n      tokenProvider: opts.tokenProvider ?? (() => this.callTokens.create(conversationId)),\n    });\n  }\n\n  /**\n   * Tear down the SDK: close the WebSocket, drop all channels.\n   * No-op for REST — fetch() doesn't keep persistent state.\n   * Call this when the user signs out or the SDK instance is\n   * being replaced.\n   */\n  destroy(): void {\n    this.realtime.disconnect();\n  }\n}\n","// Single source of truth for the SDK version at runtime. Must match\n// packages/sdk/package.json — version.test.ts asserts it, because this\n// silently drifted to 2.0.10 while the package shipped 2.1.6 and the\n// old test only checked that it was semver-shaped.\nexport const version = '2.19.0';\n"]}