# stream-provider ## Purpose `` is the singleton React surface that owns the live `StreamSession` for a tree. It calls the caller-supplied `sessionFactory` exactly once per provider instance, subscribes to the seven session event channels (`state-changed`, `interruption`, `peers-changed`, `mixer-changed`, `levels-changed`, `recording-changed`, `permission-changed`), and increments a render-bump counter on every tick so descendant hooks observe a fresh snapshot of session state. The factory pattern keeps `@suaveplan/react-audio-stream` transport-agnostic: the consumer decides whether the underlying transport is WebRTC, WebSocket, Trystero, or a test fake, and the provider never imports any transport directly. Cleanup on unmount calls `session.disconnect()` so the audio engine + socket are torn down deterministically. ## Features - StrictMode-safe singleton via `useRef`-guarded lazy construction. - Caller-injected `sessionFactory` — zero transport coupling at provider tier. - Render-bump counter fans seven event channels into one re-render path. - Cleanup-on-unmount disconnects the session and detaches every listener. - Memoised context value — only the `version` field changes per tick. ## Usage: Basic ```tsx import { StreamProvider } from "@suaveplan/react-audio-stream/provider"; import { createStreamSession } from "./my-session-factory"; export function App({ children }: { children: React.ReactNode }) { return ( createStreamSession({ transport: "webrtc" })}> {children} ); } ``` ## Usage: Advanced ```tsx import { StreamProvider } from "@suaveplan/react-audio-stream/provider"; import { useMemo } from "react"; export function ScopedRoom({ roomId, children }: { roomId: string; children: React.ReactNode }) { const factory = useMemo( () => () => createStreamSession({ transport: "trystero", initialRoomId: roomId }), [roomId] ); return {children}; } ``` Keying the provider on `roomId` (``) forces a fresh session when the room changes, because the singleton is per-instance. ## API Reference - `StreamProviderProps` — `{ sessionFactory: StreamSessionFactory; children?: ReactNode }` - `StreamProvider(props)` — renders a `StreamReactContext.Provider` with `{ session, version }`. ## Implementation Notes The seven event subscriptions all funnel into a single `setVersion((v) => v + 1)` call, which collapses bursts into a single React render pass thanks to automatic batching. The disconnect call on unmount is wrapped in `Promise.resolve` so the same code path handles both sync and async session implementations, and the rejection branch swallows errors (any failure already surfaced as an `interruption` event before the listener detach).