/** Where the user is in the queue lifecycle. */ type QueuePhase = /** Not connected and not trying to. */ "idle" /** Socket opening / waiting for the first server message. */ | "connecting" /** In line, not yet at the front. */ | "queued" /** At the front, capacity slot reserved — call `claim()` to enter. No session yet. */ | "admitted" /** Claimed; waiting for the server to create the session and send `session_ready`. */ | "starting" /** Session is ready (`sessionId` set); attach with the SDK. */ | "active" /** Time ran out or the slot was reclaimed by the server. */ | "expired" /** Refused entry (e.g. duplicate tab). */ | "rejected" /** Socket closed without reaching a terminal phase. */ | "disconnected"; /** Immutable snapshot of the queue client. Re-emitted on every change. */ interface QueueState { phase: QueuePhase; /** 1-based position in line; 0 when not queued. */ position: number; /** Total people in line. */ total: number; /** Sessions currently active across all users. */ active: number; /** Total live users the server allows (maxSessions × usersPerSession). */ capacity: number; /** Current short-lived Reactor JWT, or null. */ token: string | null; /** Unix epoch seconds at which `token` expires. */ tokenExpiresAt: number | null; /** Unix epoch ms at which the user's session ends (known after admit/claim). */ sessionEndsAt: number | null; /** Full session budget (ms) the slot grants after claim; null until admitted. */ sessionDurationMs: number | null; /** Seconds left as of the last `time_warning`, else null. */ secondsLeft: number | null; /** Reactor session id from the server (set on `session_ready`). */ sessionId: string | null; /** Server-minted WebRTC connection id (set on `session_ready`); pass with sessionId. */ connectionId: number | null; /** Reason for the most recent rejection/expiry/error, if any. */ reason: string | null; } declare const INITIAL_STATE: QueueState; interface ReactorQueueClientOptions { /** PartyKit host, e.g. `my-app.username.partykit.dev` or `127.0.0.1:1999` for dev. */ host: string; /** Room id. Must match the server. Defaults to the protocol default room. */ room?: string; /** PartyKit party (server binding) name. Defaults to `"main"`. */ party?: string; /** Stable per-browser id; auto-generated + persisted in localStorage if omitted. */ clientId?: string; /** Connect immediately on construction. Default false (the React provider sets this). */ autoConnect?: boolean; /** Refresh the JWT this many ms before it expires. */ tokenSkewMs?: number; /** How long `getJwt()` waits for a fresh token before rejecting. */ tokenRequestTimeoutMs?: number; /** Auto re-join this many ms after a `rejected` (e.g. duplicate tab clears). 0 disables. */ retryRejectedMs?: number; } type Listener = (state: QueueState) => void; /** * Framework-agnostic queue client. Manages one PartyKit WebSocket, tracks queue * state, and exposes a {@link ReactorQueueClient.getJwt} resolver that hands a * fresh short-lived Reactor JWT to the Reactor SDK on demand. * * It is intentionally decoupled from `@reactor-team/js-sdk`: you wire the two * together by passing `getJwt` to the SDK and `connectOptions.sessionId` from * {@link ReactorQueueClient.getState}'s `sessionId` (set on admission). */ declare class ReactorQueueClient { private readonly opts; private socket; private retryTimer; private refreshTimer; private destroyed; private state; private listeners; private pendingToken; constructor(options: ReactorQueueClientOptions); getState(): QueueState; subscribe(listener: Listener): () => void; private setState; connect(): void; /** * Leave the queue / release the slot and do not auto-rejoin. Returns to * `idle` — from the SDK's perspective leaving and never-having-joined are the * same state; the app decides whether to show a "rejoin?" prompt. The cached * token is intentionally kept so any in-flight SDK cleanup (e.g. its * `DELETE /sessions`) can still resolve a JWT during teardown. */ leave(): void; /** Re-enter the line (e.g. after expiry). */ rejoin(): void; /** * "I'm entering the demo now." The server creates the Reactor session and * replies with `session_ready` (carrying `sessionId`). Until then we sit in * `starting` so the UI can show a spinner; we do not have a `sessionId` yet. */ claim(): void; /** * The Reactor session ended client-side (e.g. the user quit the turn): free * the slot so the queue slides, and return to `idle` so the app can show its * menu or a "play again" prompt. From an in-session phase this mirrors * {@link leave} — tear the socket down and reset to `idle` — but it sends * `session_ended` (not `leave`) so the server admits the next person, and it * drops the token: unlike `leave`, the session is already over, so no * in-flight SDK `DELETE /sessions` needs a JWT. * * Without the phase reset the client would be wedged in `active` with no * `sessionId` ("phantom-active"), a state nothing else recovers from. Re-enter * the line with {@link rejoin} (the server only re-queues on connect). * * This also doubles as unmount cleanup, so it can fire *after* the server has * already moved us to a terminal phase (`expired`/`rejected`) or after * `leave()` set `idle`. In those cases we only clear the session fields and * leave the existing phase — and the already-closed socket — untouched. */ endSession(): void; /** Tear everything down. The instance is unusable afterwards. */ destroy(): void; /** * Resolver compatible with the Reactor SDK's `getJwt` option. Returns the * cached token while it's fresh, otherwise asks the server for a new one over * the WebSocket and resolves when it arrives. * * Bound as an arrow so it can be passed directly: `getJwt={queue.getJwt}`. */ getJwt: () => Promise; private requestToken; /** * Keep the cached token warm: refresh it shortly before it expires so the SDK * never has to block on a round-trip mid-session. Best-effort; failures are * swallowed because the reactive {@link getJwt} path is the real guarantee. */ private scheduleTokenRefresh; private clearRefresh; private resolvePending; private failPending; private handleMessage; private handleClose; private send; private teardownSocket; private scheduleRetry; private clearRetry; } export { INITIAL_STATE as I, type QueuePhase as Q, ReactorQueueClient as R, type QueueState as a, type ReactorQueueClientOptions as b };