@exhumer/signalr-client 1.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/http-client.ts","../src/constants.ts","../src/messages.ts","../src/protocols/json-hub-protocol.ts","../src/transports/websocket-transport.ts","../src/transports/sse-transport.ts","../src/transports/long-polling-transport.ts","../src/logger.ts","../src/errors.ts","../src/hub-connection.ts","../src/hub-connection-builder.ts","../src/protocols/msgpack-hub-protocol.ts","../src/ws-client.ts"],"sourcesContent":["/**\n * @signalr/client\n *\n * ASP.NET Core SignalR client for Node.js.\n * HTTP and WebSocket layers are backed by undici.\n *\n * @example\n * ```ts\n * import { HubConnectionBuilder, LogLevel } from '@signalr/client';\n *\n * const connection = new HubConnectionBuilder()\n * .withUrl('https://example.com/chathub')\n * .configureLogging(LogLevel.Information)\n * .withAutomaticReconnect()\n * .build();\n *\n * connection.on('ReceiveMessage', (user: string, message: string) => {\n * console.log(`${user}: ${message}`);\n * });\n *\n * await connection.start();\n * const result = await connection.invoke<string>('Echo', 'hello');\n * await connection.stop();\n * ```\n */\n\n// ── Connection ────────────────────────────────────────────────────────────────\nexport { HubConnection } from './hub-connection.js';\nexport type { HubConnectionOptions } from './hub-connection.js';\nexport { HubConnectionBuilder, DefaultReconnectPolicy } from './hub-connection-builder.js';\nexport type { UrlOptions } from './hub-connection-builder.js';\n\n// ── Protocol ──────────────────────────────────────────────────────────────────\nexport { JsonHubProtocol, parseHandshakeResponse, HANDSHAKE_REQUEST } from './protocols/json-hub-protocol.js';\nexport type { HandshakeResponse, HandshakeParseResult } from './protocols/json-hub-protocol.js';\n\nexport {\n MsgpackHubProtocol,\n HANDSHAKE_REQUEST as MSGPACK_HANDSHAKE_REQUEST,\n} from './protocols/msgpack-hub-protocol.js';\n\n// ── Messages (discriminated union + type guards) ───────────────────────────────\nexport {\n toInvocationId,\n assertNever,\n isInvocationMessage,\n isStreamItemMessage,\n isCompletionMessage,\n isStreamInvocationMessage,\n isCancelInvocationMessage,\n isPingMessage,\n isCloseMessage,\n} from './messages.js';\nexport type {\n InvocationId,\n MessageHeaders,\n HubMessage,\n InvocationMessage,\n StreamItemMessage,\n CompletionMessage,\n StreamInvocationMessage,\n CancelInvocationMessage,\n PingMessage,\n CloseMessage,\n} from './messages.js';\n\n// ── Enumerations & constants ──────────────────────────────────────────────────\nexport {\n MessageType,\n HubConnectionState,\n LogLevel,\n HttpTransportType,\n TransferFormat,\n RECORD_SEPARATOR,\n NEGOTIATE_VERSION,\n DEFAULT_TIMEOUT_IN_MS,\n DEFAULT_PING_INTERVAL_IN_MS,\n DEFAULT_SERVER_TIMEOUT_IN_MS,\n} from './constants.js';\nexport type { MessageTypeValue } from './constants.js';\n\n// ── Interfaces (consumers can implement / augment these) ──────────────────────\nexport type {\n ILogger,\n ITransport,\n IHubProtocol,\n IHttpClient,\n IRetryPolicy,\n RetryContext,\n IStreamResult,\n IStreamSubscriber,\n ISubscription,\n NegotiateResponse,\n AvailableTransport,\n HttpResponse,\n StreamResult,\n /** undici Dispatcher - re-exported so callers need not import undici directly */\n Dispatcher,\n} from './interfaces.js';\n\n// ── Loggers ───────────────────────────────────────────────────────────────────\nexport { ConsoleLogger, NullLogger } from './logger.js';\n\n// ── Errors ────────────────────────────────────────────────────────────────────\nexport {\n HubError,\n AbortError,\n TransportError,\n HandshakeError,\n UnsupportedTransportError,\n isHubError,\n isAbortError,\n isTransportError,\n} from './errors.js';\n\n// ── HTTP clients ──────────────────────────────────────────────────────────────\n//\n// Five implementations, each using a different undici primitive.\n// `HttpClient` is an alias for `DispatchHttpClient` (backward compat).\n//\nexport {\n /** Default client - uses undici.request() */\n RequestHttpClient,\n /** WHATWG-compatible client - uses undici.fetch() */\n FetchHttpClient,\n /** Factory-callback client - uses undici.stream() */\n StreamHttpClient,\n /** Duplex-pipe client - uses undici.pipeline() */\n PipelineHttpClient,\n /** Low-level handler client - uses Dispatcher#dispatch() */\n DispatchHttpClient,\n /** Alias for DispatchHttpClient (backward compatibility) */\n HttpClient,\n} from './http-client.js';\nexport type { RequestOptions, HttpClientOptions, HttpMethod } from './http-client.js';\n\n// ── Transports (exposed for advanced / custom use) ────────────────────────────\nexport { WebSocketTransport } from './transports/websocket-transport.js';\nexport { ServerSentEventsTransport } from './transports/sse-transport.js';\nexport { LongPollingTransport } from './transports/long-polling-transport.js';\n\n// ── Low-level hand-rolled WebSocket client (kept for direct use if needed) ────\nexport { WebSocketClient, WebSocketReadyState } from './ws-client.js';\n\n// ── Cookie support ────────────────────────────────────────────────────────────\n//\n// Re-exported so consumers can use CookieJar, CookieAgent, and the low-level\n// `cookie` interceptor without a separate `npm install tough-cookie @exhumer/undici-cookie-agent`.\n//\n// Typical usage:\n//\n// import { HubConnectionBuilder, CookieJar } from '@exhumer/signalr-client';\n//\n// const jar = new CookieJar();\n// const conn = new HubConnectionBuilder()\n// .withUrl('https://example.com/hub')\n// .withCookies(jar) // ← enables automatic cookie handling\n// .build();\n//\n// await conn.start();\n// // jar now contains any cookies set by the server during negotiate\n//\n// To combine cookie handling with a custom dispatcher (e.g. ProxyAgent):\n//\n// import { ProxyAgent } from 'undici';\n// import { cookie, CookieJar } from '@exhumer/signalr-client';\n//\n// const jar = new CookieJar();\n// const agent = new ProxyAgent('http://proxy:8080');\n// const agentWithCookies = agent.compose(cookie({ jar }));\n//\n// const conn = new HubConnectionBuilder()\n// .withUrl('https://example.com/hub')\n// .withDispatcher(agentWithCookies)\n// .build();\n//\nexport { CookieJar } from 'tough-cookie';\nexport { CookieAgent, cookie } from '@exhumer/undici-cookie-agent';\n","/**\n * http-client.ts\n *\n * Five HTTP client implementations backed by undici, each wrapping a different\n * undici primitive. All five satisfy the `IHttpClient` contract so any one\n * can be used wherever an HTTP client is required (negotiate, SSE, polling…).\n *\n * ┌────────────────────┬───────────────────────────────────────────────────┐\n * │ Class │ undici primitive │\n * ├────────────────────┼───────────────────────────────────────────────────┤\n * │ RequestHttpClient │ undici.request() │\n * │ FetchHttpClient │ undici.fetch() (WHATWG-compatible) │\n * │ StreamHttpClient │ undici.stream() (factory-based streaming) │\n * │ PipelineHttpClient │ undici.pipeline() (Duplex pipe chain) │\n * │ DispatchHttpClient │ Dispatcher#dispatch (low-level handler interface) ← DEFAULT │\n * └────────────────────┴───────────────────────────────────────────────────┘\n *\n * Dispatcher (session-level):\n * Every client accepts an optional `dispatcher` option. Pass an undici\n * `Agent`, `Pool`, `Client`, `ProxyAgent`, etc. to customise connection\n * pooling, proxy routing, TLS, or any other transport-level behaviour for\n * the entire client session. When omitted, undici's process-global\n * default agent is used (`getGlobalDispatcher()`).\n *\n * HttpClient:\n * An alias for `DispatchHttpClient` so existing code that imported\n * `HttpClient` continues to work without changes.\n */\n\nimport { PassThrough, Readable } from 'node:stream';\nimport {\n request as undiciRequest,\n stream as undiciStream,\n pipeline as undiciPipeline,\n fetch as undiciFetch,\n getGlobalDispatcher,\n type Dispatcher,\n} from 'undici';\n\nimport type { HttpResponse, StreamResult, IHttpClient } from './interfaces.js';\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';\n\n/**\n * Per-request options accepted by every client method.\n * These mirror the previous `node:http`-based API surface exactly so callers\n * do not need to be changed when switching client implementations.\n */\nexport interface RequestOptions {\n /** Per-request headers merged on top of the instance-level defaults. */\n readonly headers?: Record<string, string>;\n /**\n * Request body.\n * Plain objects are serialised to JSON automatically.\n * Strings are sent as-is (set Content-Type explicitly if needed).\n */\n readonly body?: string | Record<string, unknown> | null;\n /** Override the session-level timeout for this single request (ms). */\n readonly timeout?: number;\n}\n\n/**\n * Session-level options shared by all client constructors.\n */\nexport interface HttpClientOptions {\n /** Headers sent with every request (merged before per-request headers). */\n readonly headers?: Record<string, string>;\n /** Default timeout in milliseconds applied to every request (default: 30 000). */\n readonly timeout?: number;\n /**\n * undici Dispatcher to use for the entire session.\n *\n * You can pass any `Dispatcher` subclass:\n * - `new undici.Agent(opts)` - connection-pool tuning\n * - `new undici.Pool(origin, opts)` - per-origin pool\n * - `new undici.Client(origin, opts)` - single connection\n * - `new undici.ProxyAgent(proxyUrl)` - HTTP proxy\n * - `new undici.MockAgent()` - in-process mocking\n *\n * When omitted the process-global dispatcher (`getGlobalDispatcher()`)\n * is used, which is undici's default `Agent`.\n */\n readonly dispatcher?: Dispatcher;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\n/**\n * Serialise the `body` option to a `Buffer` (or `null` for bodyless requests).\n * Returns the buffer AND the inferred Content-Type so callers can set the\n * header automatically.\n */\nfunction prepareBody(\n body: string | Record<string, unknown> | null | undefined,\n): { buf: Buffer | null; inferredContentType: string | null } {\n if (body == null) return { buf: null, inferredContentType: null };\n if (typeof body === 'string') {\n return { buf: Buffer.from(body, 'utf8'), inferredContentType: null };\n }\n return {\n buf: Buffer.from(JSON.stringify(body), 'utf8'),\n inferredContentType: 'application/json',\n };\n}\n\n/**\n * Merge session-level default headers with per-request headers.\n * Per-request headers win on collision.\n * Injects Content-Length and Content-Type when a body is present.\n */\nfunction buildHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n body: Buffer | null,\n inferredContentType: string | null,\n): Record<string, string> {\n const merged: Record<string, string> = { ...defaults, ...(overrides ?? {}) };\n if (body !== null) {\n merged['content-length'] = String(body.length);\n if (!merged['content-type'] && inferredContentType !== null) {\n merged['content-type'] = inferredContentType;\n }\n }\n return merged;\n}\n\n/**\n * Normalise an undici response headers object\n * (`Record<string, string | string[]>`) to our `HttpResponse.headers` shape\n * (`Record<string, string | string[] | undefined>`).\n */\nfunction normaliseHeaders(\n h: Record<string, string | string[]>,\n): Record<string, string | string[] | undefined> {\n // The shapes are structurally compatible; we just widen the type.\n return h as Record<string, string | string[] | undefined>;\n}\n\n// ─── Abstract base ────────────────────────────────────────────────────────────\n\n/**\n * Holds the session-level options and exposes the convenience wrappers\n * (`get`, `post`, `delete`) that delegate to the abstract `request` method.\n *\n * Concrete subclasses only need to implement `request()` and `stream()`.\n */\nabstract class BaseUndiciClient implements IHttpClient {\n /** Default headers merged into every outgoing request. */\n protected readonly defaultHeaders: Record<string, string>;\n /** Session-level request timeout in milliseconds. */\n protected readonly defaultTimeout: number;\n /**\n * Shared undici Dispatcher. May be an Agent, Pool, Client, ProxyAgent, etc.\n * Defaults to undici's process-global agent when not specified.\n */\n protected readonly dispatcher: Dispatcher;\n\n constructor(options: HttpClientOptions = {}) {\n this.defaultHeaders = options.headers ?? {};\n this.defaultTimeout = options.timeout ?? 30_000;\n this.dispatcher = options.dispatcher ?? getGlobalDispatcher();\n }\n\n // Convenience wrappers ──────────────────────────────────────────────────────\n\n get(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('GET', url, options);\n }\n\n post(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('POST', url, options);\n }\n\n delete(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('DELETE', url, options);\n }\n\n // Abstract surface - each subclass provides its own undici primitive ────────\n\n abstract request(\n method: HttpMethod,\n url: string,\n options?: RequestOptions,\n ): Promise<HttpResponse>;\n\n abstract stream(\n method: HttpMethod,\n url: string,\n options?: RequestOptions,\n ): Promise<StreamResult>;\n}\n\n// ─── 1. RequestHttpClient ─────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.request()`.\n *\n * `undici.request` is the recommended high-level API for most use-cases.\n * It returns a Promise that resolves with `{ statusCode, headers, body }`\n * where `body` is an undici `BodyReadable` (a Node `Readable` subclass).\n *\n * For buffered responses (`request()`) we call `body.text()` to collect the\n * full response. For streaming responses (`stream()`) we return `body`\n * directly as the `StreamResult.body` Readable, giving the caller zero-copy\n * access to the response stream.\n *\n */\nexport class RequestHttpClient extends BaseUndiciClient {\n /**\n * Buffered request - collects the entire response body as a string.\n *\n * Timeout is implemented via undici's built-in `headersTimeout` /\n * `bodyTimeout` options rather than an external `setTimeout`.\n */\n override async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n const { statusCode, headers: respHeaders, body } = await undiciRequest(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n });\n\n const text = await body.text();\n\n return {\n status: statusCode,\n headers: normaliseHeaders(respHeaders as Record<string, string | string[]>),\n body: text,\n };\n }\n\n /**\n * Streaming request - returns the response body `Readable` without\n * buffering. Used by SSE and long-polling transports.\n *\n * The `abort()` method destroys the underlying socket and the body stream.\n */\n override async stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const { statusCode, headers: respHeaders, body } = await undiciRequest(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n // No bodyTimeout here - SSE connections are intentionally long-lived.\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n });\n\n return {\n statusCode,\n headers: normaliseHeaders(respHeaders as Record<string, string | string[]>),\n body: body as unknown as Readable,\n abort: () => body.destroy(),\n };\n }\n}\n\n// ─── 2. FetchHttpClient ───────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.fetch()`.\n *\n * `undici.fetch` is undici's WHATWG-compatible Fetch implementation.\n * It accepts the same options as the browser `fetch()` API, plus an\n * undici-specific `dispatcher` field for custom transport control.\n *\n * Useful when you need browser API compatibility (e.g., tests that run in\n * both Node and a browser-like environment) or when consuming WHATWG `Response`\n * helpers such as `res.json()` / `res.formData()`.\n *\n * For `stream()` we convert the WHATWG `ReadableStream<Uint8Array>` body to a\n * Node.js `Readable` via `Readable.fromWeb()` (Node 17+).\n */\nexport class FetchHttpClient extends BaseUndiciClient {\n override async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const ac = new AbortController();\n const timeout = options.timeout ?? this.defaultTimeout;\n const timer = timeout > 0\n ? setTimeout(() => ac.abort(new Error(`HTTP request timed out after ${timeout} ms`)), timeout)\n : null;\n\n try {\n const res = await undiciFetch(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n signal: ac.signal,\n // undici-specific: override the dispatcher for this request.\n // undici's fetch type is defined in two conflicting locations\n // (undici-types bundled with @types/node AND undici's own .d.ts),\n // so the intersection cast doesn't satisfy either. The double-cast\n // via `unknown` sidesteps the conflict without losing safety: at\n // runtime undici.fetch() accepts exactly this shape.\n dispatcher: this.dispatcher,\n } as unknown as Parameters<typeof undiciFetch>[1]);\n\n const text = await res.text();\n if (timer !== null) clearTimeout(timer);\n\n // Convert Headers object to plain Record\n const respHeaders: Record<string, string | string[] | undefined> = {};\n res.headers.forEach((value, key) => { respHeaders[key] = value; });\n\n return { status: res.status, headers: respHeaders, body: text };\n } catch (err) {\n if (timer !== null) clearTimeout(timer);\n throw err;\n }\n }\n\n override async stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const ac = new AbortController();\n\n const res = await undiciFetch(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n signal: ac.signal,\n dispatcher: this.dispatcher,\n } as unknown as Parameters<typeof undiciFetch>[1]);\n\n // Convert WHATWG ReadableStream → Node Readable\n const body = Readable.fromWeb(\n res.body as Parameters<typeof Readable.fromWeb>[0],\n );\n\n const respHeaders: Record<string, string | string[] | undefined> = {};\n res.headers.forEach((value, key) => { respHeaders[key] = value; });\n\n return {\n statusCode: res.status,\n headers: respHeaders,\n body,\n abort: () => { ac.abort(); body.destroy(); },\n };\n }\n}\n\n// ─── 3. StreamHttpClient ──────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.stream()`.\n *\n * `undici.stream` uses a *factory callback* pattern: you supply a function\n * that receives `{ statusCode, headers, body }` and must return a\n * `Writable` to which the response body is piped.\n *\n * This makes it ideal when you want to pipe response bytes directly to a\n * destination (e.g., a file, a transform, or a compression stream) without\n * ever holding the entire response in memory.\n *\n * For buffered `request()` we use a `PassThrough` as the sink and collect\n * its output. For streaming `stream()` we expose the PassThrough's\n * readable side as `StreamResult.body`.\n */\nexport class StreamHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n let statusCode = 0;\n let respHeaders: Record<string, string | string[]> = {};\n const chunks: Buffer[] = [];\n\n return undiciStream(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode: sc, headers: h }) => {\n statusCode = sc;\n respHeaders = h as Record<string, string | string[]>;\n\n // Sink that collects the response bytes\n const sink = new PassThrough();\n sink.on('data', (chunk: Buffer) => chunks.push(chunk));\n return sink;\n },\n ).then(() => ({\n status: statusCode,\n headers: normaliseHeaders(respHeaders),\n body: Buffer.concat(chunks).toString('utf8'),\n }));\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n return new Promise<StreamResult>((resolve, reject) => {\n // The PassThrough is the pipe target inside the factory AND the readable\n // we hand back to the caller - the same object plays both roles.\n const pt = new PassThrough();\n\n undiciStream(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode, headers: h }) => {\n resolve({\n statusCode,\n headers: normaliseHeaders(h as Record<string, string | string[]>),\n body: pt,\n abort: () => pt.destroy(),\n });\n // Return the same PassThrough as the writable sink.\n // undici pipes the response body into it; callers read from it.\n return pt;\n },\n ).catch((err: unknown) => {\n // Connection failed before headers: Promise has not resolved, so no\n // caller holds a reference to `pt`. Destroy it without an error arg\n // to avoid emitting an unhandled 'error' event on an orphaned stream.\n pt.destroy();\n reject(err);\n });\n });\n }\n}\n\n// ─── 4. PipelineHttpClient ────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.pipeline()`.\n *\n * `undici.pipeline` returns a `stream.Duplex`:\n * - **Writable side**: the request body (write / pipe into it).\n * - **Readable side**: whatever your handler function *returns*.\n *\n * The handler receives `{ statusCode, headers, body }` and must return a\n * `Readable`. Whatever that readable emits becomes the duplex's output.\n *\n * Typical use: response transformation pipelines\n * `pipeline(url, opts, ({ body }) => body.pipe(gunzip()))`\n *\n * For `request()` we return the raw body from the handler, collect the duplex\n * output into a buffer, and resolve with the buffered string.\n *\n * For `stream()` we return the raw body from the handler and give the caller\n * the duplex's readable side directly - zero extra buffering.\n */\nexport class PipelineHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n return new Promise<HttpResponse>((resolve, reject) => {\n let statusCode = 0;\n let respHeaders: Record<string, string | string[]> = {};\n const chunks: Buffer[] = [];\n\n const duplex = undiciPipeline(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode: sc, headers: h, body }) => {\n statusCode = sc;\n respHeaders = h as Record<string, string | string[]>;\n // Return the body readable - it becomes the duplex output.\n return body;\n },\n );\n\n duplex.on('data', (chunk: Buffer) => chunks.push(chunk));\n duplex.on('end', () =>\n resolve({\n status: statusCode,\n headers: normaliseHeaders(respHeaders),\n body: Buffer.concat(chunks).toString('utf8'),\n }),\n );\n duplex.on('error', reject);\n\n // Signal end-of-request-body (required even for bodyless requests)\n if (buf !== null) {\n duplex.write(buf);\n }\n duplex.end();\n });\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n return new Promise<StreamResult>((resolve, reject) => {\n let resolved = false;\n\n // `duplex` is assigned by `undiciPipeline` (synchronously before any\n // async I/O), so the closure inside the handler can safely reference it.\n // eslint-disable-next-line prefer-const\n let duplex: ReturnType<typeof undiciPipeline>;\n\n duplex = undiciPipeline(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode, headers: h, body }) => {\n if (!resolved) {\n resolved = true;\n resolve({\n statusCode,\n headers: normaliseHeaders(h as Record<string, string | string[]>),\n // The duplex IS the readable - its output is the body.\n body: duplex as unknown as Readable,\n abort: () => duplex.destroy(),\n });\n }\n // Return body so pipeline routes it to the duplex's readable side.\n return body;\n },\n );\n\n duplex.on('error', (err: Error) => {\n if (!resolved) reject(err);\n });\n\n if (buf !== null) duplex.write(buf);\n duplex.end();\n });\n }\n}\n\n// ─── 5. DispatchHttpClient (DEFAULT) ─────────────────────────────────────────\n\n/**\n * HTTP client backed by `Dispatcher#dispatch()`.\n *\n * `dispatch` is the *lowest-level* undici API. It exposes the full\n * request/response lifecycle as a handler interface (undici 8+):\n *\n * onRequestStart → request is about to be sent; receives DispatchController\n * onResponseStart → response status + headers received\n * onResponseData → response body chunk\n * onResponseEnd → response fully consumed\n * onResponseError → error at any stage\n *\n * This gives you maximum control: you can abort mid-stream, transform\n * chunks on the fly, or implement custom back-pressure logic.\n *\n * Unlike the other clients, `DispatchHttpClient` *requires* a `Dispatcher`\n * (an `Agent`, `Pool`, or `Client` instance). If none is provided the\n * process-global agent is used.\n *\n * Note: `dispatcher.dispatch()` needs the URL split into `origin` + `path`\n * (for `Agent` / `Pool`) or just `path` (for `Client` whose origin is\n * already bound). We always pass `origin` for maximum compatibility.\n */\nexport class DispatchHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const parsed = new URL(url);\n const timeout = options.timeout ?? this.defaultTimeout;\n\n return new Promise<HttpResponse>((resolve, reject) => {\n let statusCode = 0;\n let respHeaders: Record<string, string | string[] | undefined> = {};\n const chunks: Buffer[] = [];\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n if (timeout > 0) {\n timer = setTimeout(() => {\n reject(new Error(`HTTP request timed out after ${timeout} ms`));\n }, timeout);\n }\n\n const clearTimer = (): void => {\n if (timer !== null) { clearTimeout(timer); timer = null; }\n };\n\n this.dispatcher.dispatch(\n {\n origin: parsed.origin,\n path: parsed.pathname + parsed.search,\n method,\n headers,\n ...(buf !== null && { body: buf }),\n },\n {\n onRequestStart: (_controller: Dispatcher.DispatchController, _context: unknown): void => {\n // socket acquired; controller available for abort if needed\n },\n\n onResponseError: (_controller: Dispatcher.DispatchController, err: Error): void => {\n clearTimer();\n reject(err);\n },\n\n onResponseStart: (\n _controller: Dispatcher.DispatchController,\n sc: number,\n headers: Record<string, string | string[] | undefined>,\n ): void => {\n statusCode = sc;\n respHeaders = headers;\n },\n\n onResponseData: (_controller: Dispatcher.DispatchController, chunk: Buffer): void => {\n chunks.push(Buffer.from(chunk));\n },\n\n onResponseEnd: (_controller: Dispatcher.DispatchController, _trailers: Record<string, string | string[] | undefined>): void => {\n clearTimer();\n resolve({\n status: statusCode,\n headers: respHeaders,\n body: Buffer.concat(chunks).toString('utf8'),\n });\n },\n } satisfies Dispatcher.DispatchHandler,\n );\n });\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const parsed = new URL(url);\n\n return new Promise<StreamResult>((resolve, reject) => {\n let resolved = false;\n // PassThrough exposes a readable side to the caller and accepts\n // body chunks pushed to it from the onResponseData handler.\n const pt = new PassThrough();\n\n let controller: Dispatcher.DispatchController | null = null;\n\n this.dispatcher.dispatch(\n {\n origin: parsed.origin,\n path: parsed.pathname + parsed.search,\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n },\n {\n onRequestStart: (ctrl: Dispatcher.DispatchController, _context: unknown): void => {\n controller = ctrl;\n },\n\n onResponseError: (_ctrl: Dispatcher.DispatchController, err: Error): void => {\n if (!resolved) {\n // Promise not yet resolved: reject it. The PassThrough stream has\n // not been handed to the caller yet, so destroy it silently to\n // avoid an unhandled 'error' event on a stream nobody is reading.\n resolved = true;\n pt.destroy();\n reject(err);\n } else {\n // Response headers were already delivered; propagate the error\n // through the stream so the caller's reader sees it.\n pt.destroy(err);\n }\n },\n\n onResponseStart: (\n _ctrl: Dispatcher.DispatchController,\n statusCode: number,\n headers: Record<string, string | string[] | undefined>,\n ): void => {\n if (!resolved) {\n resolved = true;\n resolve({\n statusCode,\n headers,\n body: pt,\n abort: () => {\n controller?.abort(new Error('Stream aborted'));\n pt.destroy();\n },\n });\n }\n },\n\n onResponseData: (_ctrl: Dispatcher.DispatchController, chunk: Buffer): void => {\n pt.write(chunk);\n },\n\n onResponseEnd: (_ctrl: Dispatcher.DispatchController, _trailers: Record<string, string | string[] | undefined>): void => {\n pt.end();\n },\n } satisfies Dispatcher.DispatchHandler,\n );\n });\n }\n}\n\n// ─── HttpClient - backward-compat alias ──────────────────────────────────────\n\n/**\n * `HttpClient` is an alias for `DispatchHttpClient` (the default).\n *\n * Existing code that `import { HttpClient }` continues to work without\n * modification. `new HttpClient(opts)` behaves identically to\n * `new DispatchHttpClient(opts)`.\n */\nexport { DispatchHttpClient as HttpClient };\n","/**\n * constants.ts\n *\n * All SignalR protocol constants, enumerations, and timing defaults.\n * Uses `as const satisfies` (TS 4.9+) so values carry their narrow literal\n * types while being verified against a constraint at compile time.\n */\n\n// ─── MessageType ──────────────────────────────────────────────────────────────\n// Each value doubles as both a runtime constant and a narrow numeric literal\n// type (used in the discriminated-union HubMessage in messages.ts).\n\nexport const MessageType = Object.freeze({\n Invocation: 1,\n StreamItem: 2,\n Completion: 3,\n StreamInvocation: 4,\n CancelInvocation: 5,\n Ping: 6,\n Close: 7,\n} as const satisfies Record<string, number>);\n\n/** Union of all valid message type numbers. */\nexport type MessageTypeValue = (typeof MessageType)[keyof typeof MessageType];\n\n// ─── HubConnectionState ───────────────────────────────────────────────────────\n\nexport const HubConnectionState = Object.freeze({\n Disconnected: 'Disconnected',\n Connecting: 'Connecting',\n Connected: 'Connected',\n Disconnecting: 'Disconnecting',\n Reconnecting: 'Reconnecting',\n} as const satisfies Record<string, string>);\n\n/** Union of all valid connection state strings. */\nexport type HubConnectionState = (typeof HubConnectionState)[keyof typeof HubConnectionState];\n\n// ─── LogLevel ─────────────────────────────────────────────────────────────────\n\nexport const LogLevel = {\n Trace: 0,\n Debug: 1,\n Information: 2,\n Warning: 3,\n Error: 4,\n Critical: 5,\n None: 6,\n} as const satisfies Record<string, number>;\n\nexport type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];\n\n// ─── HttpTransportType ────────────────────────────────────────────────────────\n\nexport const HttpTransportType = {\n None: 0,\n WebSockets: 1,\n ServerSentEvents: 2,\n LongPolling: 4,\n} as const satisfies Record<string, number>;\n\n/** Bitmask of enabled transports - values can be OR-ed together. */\nexport type HttpTransportType = (typeof HttpTransportType)[keyof typeof HttpTransportType];\n\n// ─── TransferFormat ───────────────────────────────────────────────────────────\n\nexport const TransferFormat = {\n Text: 1,\n Binary: 2,\n} as const satisfies Record<string, number>;\n\nexport type TransferFormat = (typeof TransferFormat)[keyof typeof TransferFormat];\n\n// ─── Protocol constants ───────────────────────────────────────────────────────\n\n/** ASCII 30 - the byte that terminates every SignalR JSON message. */\nexport const RECORD_SEPARATOR = '\\x1e' as const;\n\n/** Negotiate version we advertise to the server. */\nexport const NEGOTIATE_VERSION = 1 as const;\n\n// ─── Timing defaults ──────────────────────────────────────────────────────────\n\nexport const DEFAULT_TIMEOUT_IN_MS = 30_000 as const;\nexport const DEFAULT_PING_INTERVAL_IN_MS = 15_000 as const;\nexport const DEFAULT_SERVER_TIMEOUT_IN_MS = 30_000 as const;\n","/**\n * messages.ts\n *\n * Full discriminated-union type definitions for every SignalR hub protocol\n * message. The `type` field on each interface carries a numeric literal type\n * derived from the `MessageType` constants so TypeScript narrows correctly\n * inside `switch` / `if` statements.\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport type { MessageType } from './constants.js';\n\n// ─── Branding ─────────────────────────────────────────────────────────────────\n\ndeclare const __invocationIdBrand: unique symbol;\n\n/**\n * Opaque wrapper around `string` for invocation IDs.\n * Prevents mixing arbitrary strings with IDs at the type level.\n */\nexport type InvocationId = string & { readonly [__invocationIdBrand]: void };\n\n/** Cast a plain string to an InvocationId (only used inside the library). */\nexport function toInvocationId(s: string): InvocationId {\n return s as InvocationId;\n}\n\n// ─── Common metadata ──────────────────────────────────────────────────────────\n\n/** Optional headers that may appear on any hub message. */\nexport type MessageHeaders = Readonly<Record<string, string>>;\n\ninterface BaseMessage {\n readonly headers?: MessageHeaders;\n}\n\n// ─── Individual message shapes ────────────────────────────────────────────────\n\ntype MT = typeof MessageType;\n\n/** Type 1 - Server→Client or Client→Server method call. */\nexport interface InvocationMessage extends BaseMessage {\n readonly type: MT['Invocation'];\n /** Absent on fire-and-forget invocations. */\n readonly invocationId?: InvocationId;\n readonly target: string;\n readonly arguments: readonly unknown[];\n readonly streamIds?: readonly string[];\n}\n\n/** Type 2 - One item from a server-streaming method. */\nexport interface StreamItemMessage extends BaseMessage {\n readonly type: MT['StreamItem'];\n readonly invocationId: InvocationId;\n readonly item: unknown;\n}\n\n/** Type 3 - Terminal result or error for an invocation / stream. */\nexport interface CompletionMessage extends BaseMessage {\n readonly type: MT['Completion'];\n readonly invocationId: InvocationId;\n readonly error?: string;\n readonly result?: unknown;\n}\n\n/** Type 4 - Client initiates a server-streaming call. */\nexport interface StreamInvocationMessage extends BaseMessage {\n readonly type: MT['StreamInvocation'];\n readonly invocationId: InvocationId;\n readonly target: string;\n readonly arguments: readonly unknown[];\n readonly streamIds?: readonly string[];\n}\n\n/** Type 5 - Client cancels an outstanding server stream. */\nexport interface CancelInvocationMessage extends BaseMessage {\n readonly type: MT['CancelInvocation'];\n readonly invocationId: InvocationId;\n}\n\n/** Type 6 - Keep-alive ping; expects no response from the other side. */\nexport interface PingMessage extends BaseMessage {\n readonly type: MT['Ping'];\n}\n\n/** Type 7 - Graceful close notification from the server. */\nexport interface CloseMessage extends BaseMessage {\n readonly type: MT['Close'];\n readonly error?: string;\n readonly allowReconnect?: boolean;\n}\n\n// ─── Union ────────────────────────────────────────────────────────────────────\n\n/** Exhaustive discriminated union of all SignalR hub protocol messages. */\nexport type HubMessage =\n | InvocationMessage\n | StreamItemMessage\n | CompletionMessage\n | StreamInvocationMessage\n | CancelInvocationMessage\n | PingMessage\n | CloseMessage;\n\n// ─── Utility: exhaustiveness helper ──────────────────────────────────────────\n\n/**\n * Asserts a code path is unreachable at compile time.\n * Use at the `default` branch of a `switch` over `HubMessage['type']`.\n */\nexport function assertNever(_x: never, label?: string): never {\n throw new Error(`Unexpected value${label ? ` for ${label}` : ''}: ${JSON.stringify(_x)}`);\n}\n\n// ─── Type guards ─────────────────────────────────────────────────────────────\n\nexport function isInvocationMessage(msg: HubMessage): msg is InvocationMessage {\n return msg.type === 1;\n}\n\nexport function isStreamItemMessage(msg: HubMessage): msg is StreamItemMessage {\n return msg.type === 2;\n}\n\nexport function isCompletionMessage(msg: HubMessage): msg is CompletionMessage {\n return msg.type === 3;\n}\n\nexport function isStreamInvocationMessage(msg: HubMessage): msg is StreamInvocationMessage {\n return msg.type === 4;\n}\n\nexport function isCancelInvocationMessage(msg: HubMessage): msg is CancelInvocationMessage {\n return msg.type === 5;\n}\n\nexport function isPingMessage(msg: HubMessage): msg is PingMessage {\n return msg.type === 6;\n}\n\nexport function isCloseMessage(msg: HubMessage): msg is CloseMessage {\n return msg.type === 7;\n}\n","/**\n * json-hub-protocol.ts\n *\n * Implements the SignalR Hub Protocol over JSON (version 1).\n *\n * Wire format: every message is JSON followed by ASCII 0x1e (RECORD_SEPARATOR).\n * A single transport payload may contain multiple messages.\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport { MessageType, TransferFormat, RECORD_SEPARATOR } from '../constants.js';\nimport type { IHubProtocol, ILogger } from '../interfaces.js';\nimport {\n type HubMessage,\n type InvocationMessage,\n type StreamInvocationMessage,\n type CancelInvocationMessage,\n type CompletionMessage,\n type StreamItemMessage,\n type PingMessage,\n type CloseMessage,\n type InvocationId,\n toInvocationId,\n} from '../messages.js';\n\n// ─── Handshake constants ──────────────────────────────────────────────────────\n\nexport const HANDSHAKE_REQUEST =\n JSON.stringify({ protocol: 'json', version: 1 }) + RECORD_SEPARATOR;\n\nexport interface HandshakeResponse {\n readonly error?: string;\n readonly minorVersion?: number;\n}\n\nexport interface HandshakeParseResult {\n /** Remainder of the input string after the handshake record (may be non-empty). */\n readonly remainder: string;\n}\n\n/**\n * Parse the first record from `data` as the server handshake response.\n * @throws {Error} if the record separator is missing or the server returned an error.\n */\nexport function parseHandshakeResponse(data: string): HandshakeParseResult {\n const idx = data.indexOf(RECORD_SEPARATOR);\n if (idx === -1) {\n throw new Error('Handshake response is missing the record separator.');\n }\n\n const raw: string = data.slice(0, idx);\n const response: HandshakeResponse = JSON.parse(raw) as HandshakeResponse;\n\n if (response.error) {\n throw new Error(`Server rejected the handshake with the error: \"${response.error}\"`);\n }\n\n return { remainder: data.slice(idx + 1) };\n}\n\n// ─── Raw message shape (before validation/narrowing) ─────────────────────────\n\ninterface RawMessage {\n type: unknown;\n invocationId?: unknown;\n target?: unknown;\n arguments?: unknown;\n streamIds?: unknown;\n item?: unknown;\n result?: unknown;\n error?: unknown;\n allowReconnect?: unknown;\n headers?: unknown;\n}\n\n// ─── Protocol class ───────────────────────────────────────────────────────────\n\nexport class JsonHubProtocol implements IHubProtocol {\n readonly name = 'json' as const;\n readonly version = 1 as const;\n readonly transferFormat = TransferFormat.Text;\n\n // ─── IHubProtocol: parseMessages ─────────────────────────────────────\n\n parseMessages(input: string | ArrayBuffer, logger: ILogger): HubMessage[] {\n const text = typeof input === 'string' ? input : new TextDecoder().decode(input);\n if (!text) return [];\n\n const messages: HubMessage[] = [];\n const parts = text.split(RECORD_SEPARATOR);\n\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n\n let raw: RawMessage;\n try {\n raw = JSON.parse(trimmed) as RawMessage;\n } catch (e) {\n throw new Error(`Error parsing message: ${(e as Error).message}. Raw value: \"${trimmed}\"`);\n }\n\n const msg = this.#coerce(raw);\n if (msg !== null) {\n messages.push(msg);\n } else {\n logger.log(3 /* Warning */, `Ignoring message with unknown type ${String(raw.type)}.`);\n }\n }\n\n return messages;\n }\n\n // ─── IHubProtocol: writeMessage ───────────────────────────────────────\n\n writeMessage(message: HubMessage): string {\n return JSON.stringify(message) + RECORD_SEPARATOR;\n }\n\n // ─── Coercion / narrowing ─────────────────────────────────────────────\n\n /**\n * Validate and narrow a raw parsed object into a typed `HubMessage`.\n * Returns `null` for unknown types (not an error - new protocol versions\n * may add types we don't know about).\n */\n #coerce(raw: RawMessage): HubMessage | null {\n const type = raw.type;\n if (typeof type !== 'number') {\n throw new Error(`Invalid message: 'type' must be a number, got ${JSON.stringify(type)}.`);\n }\n\n switch (type) {\n case MessageType.Invocation:\n return this.#coerceInvocation(raw);\n case MessageType.StreamItem:\n return this.#coerceStreamItem(raw);\n case MessageType.Completion:\n return this.#coerceCompletion(raw);\n case MessageType.StreamInvocation:\n return this.#coerceStreamInvocation(raw);\n case MessageType.CancelInvocation:\n return this.#coerceCancelInvocation(raw);\n case MessageType.Ping:\n return this.#coercePing();\n case MessageType.Close:\n return this.#coerceClose(raw);\n default:\n return null;\n }\n }\n\n #coerceInvocation(raw: RawMessage): InvocationMessage {\n if (typeof raw.target !== 'string') {\n throw new Error(\"Invalid Invocation message: 'target' must be a string.\");\n }\n if (!Array.isArray(raw.arguments)) {\n throw new Error(\"Invalid Invocation message: 'arguments' must be an array.\");\n }\n return {\n type: MessageType.Invocation,\n target: raw.target,\n arguments: raw.arguments as unknown[],\n ...(raw.invocationId != null && { invocationId: toInvocationId(String(raw.invocationId)) }),\n ...(Array.isArray(raw.streamIds) && { streamIds: raw.streamIds as string[] }),\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n #coerceStreamItem(raw: RawMessage): StreamItemMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid StreamItem message: 'invocationId' is required.\");\n }\n return {\n type: MessageType.StreamItem,\n invocationId: toInvocationId(String(raw.invocationId)),\n item: raw.item,\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n #coerceCompletion(raw: RawMessage): CompletionMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid Completion message: 'invocationId' is required.\");\n }\n if (raw.error != null && raw.result != null) {\n throw new Error(\"Invalid Completion message: 'error' and 'result' are mutually exclusive.\");\n }\n return {\n type: MessageType.Completion,\n invocationId: toInvocationId(String(raw.invocationId)),\n ...(raw.error != null && { error: String(raw.error) }),\n ...(raw.result != null && { result: raw.result }),\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n #coerceStreamInvocation(raw: RawMessage): StreamInvocationMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid StreamInvocation message: 'invocationId' is required.\");\n }\n if (typeof raw.target !== 'string') {\n throw new Error(\"Invalid StreamInvocation message: 'target' must be a string.\");\n }\n if (!Array.isArray(raw.arguments)) {\n throw new Error(\"Invalid StreamInvocation message: 'arguments' must be an array.\");\n }\n return {\n type: MessageType.StreamInvocation,\n invocationId: toInvocationId(String(raw.invocationId)),\n target: raw.target,\n arguments: raw.arguments as unknown[],\n ...(Array.isArray(raw.streamIds) && { streamIds: raw.streamIds as string[] }),\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n #coerceCancelInvocation(raw: RawMessage): CancelInvocationMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid CancelInvocation message: 'invocationId' is required.\");\n }\n return {\n type: MessageType.CancelInvocation,\n invocationId: toInvocationId(String(raw.invocationId)),\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n #coercePing(): PingMessage {\n return { type: MessageType.Ping };\n }\n\n #coerceClose(raw: RawMessage): CloseMessage {\n return {\n type: MessageType.Close,\n ...(raw.error != null && { error: String(raw.error) }),\n ...(raw.allowReconnect != null && { allowReconnect: Boolean(raw.allowReconnect) }),\n ...(raw.headers != null && { headers: raw.headers as Record<string, string> }),\n };\n }\n\n // ─── Static message factories ─────────────────────────────────────────\n\n static invocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n /**\n * Fire-and-forget (no `invocationId` → server won't send a Completion).\n */\n static send(\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static streamInvocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): StreamInvocationMessage {\n return {\n type: MessageType.StreamInvocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static cancelInvocation(invocationId: InvocationId): CancelInvocationMessage {\n return { type: MessageType.CancelInvocation, invocationId };\n }\n\n static streamItem(invocationId: InvocationId, item: unknown): StreamItemMessage {\n return { type: MessageType.StreamItem, invocationId, item };\n }\n\n static completion(\n invocationId: InvocationId,\n result: unknown,\n error: string | null,\n ): CompletionMessage {\n return {\n type: MessageType.Completion,\n invocationId,\n ...(error != null && { error }),\n ...(result != null && { result }),\n };\n }\n\n static ping(): PingMessage {\n return { type: MessageType.Ping };\n }\n}\n","/**\n * websocket-transport.ts\n *\n * SignalR WebSocket transport - rewritten to use undici's built-in\n * WHATWG-compatible `WebSocket` implementation.\n *\n * Why undici WebSocket instead of the hand-rolled RFC 6455 client?\n * ─────────────────────────────────────────────────────────────────\n * • undici is the HTTP engine Node.js core ships with (≥ v18).\n * • Its WebSocket implementation passes the Autobahn test suite.\n * • It accepts the same `Dispatcher` used by the HTTP clients, so the\n * entire SignalR session (negotiate, handshake, upgrade) shares a single\n * connection pool / proxy config.\n * • It supports custom headers on the upgrade request (needed for auth\n * and extra headers), which the browser WebSocket API does not.\n *\n * undici WebSocket quirks in Node.js\n * ────────────────────────────────────\n * • The constructor signature is:\n * new WebSocket(url, { headers?, dispatcher?, protocols? })\n * The `headers` and `dispatcher` fields are undici extensions not in the\n * WHATWG spec.\n * • `MessageEvent.data` type depends on `ws.binaryType`:\n * 'arraybuffer' (what we set) → ArrayBuffer\n * 'blob' → Blob\n * We set `binaryType = 'arraybuffer'` and convert ArrayBuffer → Buffer on\n * receipt. ('nodebuffer' is a valid undici runtime value but is absent from\n * the WHATWG BinaryType union in undici's TypeScript declarations.)\n * • `CloseEvent.code` / `.reason` behave identically to the browser.\n */\n\nimport { WebSocket } from 'undici';\nimport type { Dispatcher } from 'undici';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\n\n// ─── ReadyState constants (mirrors window.WebSocket) ─────────────────────────\n\nexport const WebSocketReadyState = Object.freeze({\n Connecting: 0,\n Open: 1,\n Closing: 2,\n Closed: 3,\n} as const satisfies Record<string, number>);\n\nexport type WebSocketReadyState =\n (typeof WebSocketReadyState)[keyof typeof WebSocketReadyState];\n\n// ─── Transport implementation ─────────────────────────────────────────────────\n\nexport class WebSocketTransport implements ITransport {\n readonly name = 'WebSockets' as const;\n\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n readonly #dispatcher: Dispatcher | undefined;\n\n #ws: WebSocket | null = null;\n\n onreceive: ((data: string | Uint8Array) => void) | null = null;\n onclose: ((error?: Error) => void) | null = null;\n\n /**\n * @param accessTokenFactory Async factory for Bearer tokens, or null.\n * @param logger Logger instance.\n * @param extraHeaders Headers forwarded on every upgrade request.\n * @param dispatcher Optional undici Dispatcher (Agent/Pool/Client/\n * ProxyAgent). When omitted, undici's default\n * global agent is used. Pass the same dispatcher\n * used by your HTTP clients to share the pool.\n */\n constructor(\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n dispatcher?: Dispatcher,\n ) {\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n this.#dispatcher = dispatcher;\n }\n\n async connect(url: string, _transferFormat: TransferFormat): Promise<void> {\n this.#logger.log(LogLevel.Trace, `(WebSockets transport) Connecting to ${url}.`);\n\n // ── Build headers ───────────────────────────────────────────────────────\n const headers: Record<string, string> = { ...this.#extraHeaders };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n // ── Convert http(s) → ws(s) ─────────────────────────────────────────────\n const wsUrl = url.replace(/^http/, 'ws');\n\n // ── Open the WebSocket ──────────────────────────────────────────────────\n // undici's WebSocket constructor accepts headers + dispatcher as its\n // second argument. These are undici-specific extensions to the spec.\n const ws = new WebSocket(wsUrl, {\n headers,\n ...(this.#dispatcher !== undefined && { dispatcher: this.#dispatcher }),\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n this.#ws = ws;\n\n // Keep binary frames as ArrayBuffer. 'nodebuffer' works at runtime but\n // is absent from the WHATWG BinaryType union in undici's type declarations,\n // so 'arraybuffer' is used here and converted to Buffer on receipt.\n ws.binaryType = 'arraybuffer';\n\n // ── Wait for the socket to be open before resolving ─────────────────────\n // We wrap the open/error events in a Promise so `connect()` only resolves\n // once the TCP + TLS + WebSocket handshake is fully complete.\n await new Promise<void>((resolve, reject) => {\n ws.addEventListener('open', () => {\n this.#logger.log(LogLevel.Information, '(WebSockets transport) Connected.');\n resolve();\n });\n\n ws.addEventListener('error', (event) => {\n // ErrorEvent is a browser DOM global absent from Node.js lib targets.\n // Cast to a structural equivalent to access `.error` / `.message`.\n const e = event as Event & { error?: unknown; message?: string };\n let err: Error;\n if (e.error instanceof Error) {\n // undici sometimes wraps the real network error (e.g. ECONNREFUSED)\n // inside `error.cause` and leaves `error.message` as an empty string.\n // Prefer the cause when the outer message is empty so callers see a\n // meaningful message (ECONNREFUSED, etc.) rather than ''.\n err = e.error.message\n ? e.error\n : (e.error.cause instanceof Error\n ? e.error.cause\n : new Error('WebSocket connection failed'));\n } else {\n err = new Error(String(e.message ?? 'WebSocket error'));\n }\n this.#logger.log(LogLevel.Error, `(WebSockets transport) Error during connect: ${err.message}`);\n reject(err);\n });\n });\n\n // ── Wire ongoing event handlers (after open) ─────────────────────────────\n\n // MessageEvent is defined in two conflicting type sources (undici-types\n // bundled inside @types/node and undici's own .d.ts). Their `.ports`\n // fields are incompatible, so typing the listener parameter as\n // `MessageEvent` triggers an overload-mismatch error. We let TypeScript\n // infer the parameter type (falling back to the generic `string` overload)\n // and then extract `.data` through a structural intersection cast.\n //\n // Because binaryType = 'arraybuffer', data is always string | ArrayBuffer.\n ws.addEventListener('message', (event) => {\n const data = (event as Event & { data: unknown }).data;\n if (typeof data === 'string') {\n this.#logger.log(LogLevel.Trace,\n `(WebSockets transport) Received text (${data.length} chars).`);\n this.onreceive?.(data);\n /* istanbul ignore else - binaryType='arraybuffer' constrains delivery\n to string | ArrayBuffer; any other type is unreachable in practice. */\n } else if (data instanceof ArrayBuffer) {\n const buf = Buffer.from(data);\n this.#logger.log(LogLevel.Trace,\n `(WebSockets transport) Received binary (${buf.length} bytes).`);\n this.onreceive?.(buf);\n }\n });\n\n // CloseEvent is a browser DOM global absent from Node.js lib targets.\n // Cast to a structural equivalent to access `.code` / `.reason`.\n ws.addEventListener('close', (event) => {\n const closeEvent = event as Event & { code: number; reason: string };\n this.#logger.log(LogLevel.Information,\n `(WebSockets transport) Socket closed (code=${closeEvent.code}).`);\n // Only call onclose for unexpected closures (not our own stop() call).\n if (this.#ws !== null) {\n this.#ws = null;\n this.onclose?.();\n }\n });\n\n ws.addEventListener('error', (event) => {\n // Errors after the initial open.\n // Same structural-cast pattern as above: ErrorEvent not in Node lib.\n if (ws.readyState !== WebSocket.CONNECTING) {\n const e = event as Event & { error?: unknown; message?: string };\n const err = e.error instanceof Error\n ? e.error\n : new Error(String(e.message ?? 'WebSocket error'));\n this.#logger.log(LogLevel.Error, `(WebSockets transport) Error: ${err.message}`);\n // Null #ws BEFORE calling onclose so the 'close' event handler that\n // fires next sees this.#ws === null and does not call onclose a second\n // time (which would start two concurrent reconnect loops).\n if (this.#ws !== null) {\n this.#ws = null;\n this.onclose?.(err);\n }\n }\n });\n }\n\n send(data: string | Uint8Array): Promise<void> {\n if (!this.#ws || this.#ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error('WebSocket is not open.'));\n }\n try {\n // undici's WebSocket.send() accepts string | ArrayBufferLike |\n // ArrayBufferView | Blob. Uint8Array satisfies ArrayBufferView.\n this.#ws.send(data);\n return Promise.resolve();\n /* istanbul ignore next - ws.send() on an already-open socket does not\n throw synchronously; this catch is a belt-and-suspenders fallback. */\n } catch (err) {\n return Promise.reject(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n stop(): Promise<void> {\n if (this.#ws) {\n const ws = this.#ws;\n this.#ws = null; // clear BEFORE close so the close handler skips onclose\n ws.close(1000, 'Normal closure');\n }\n return Promise.resolve();\n }\n}\n","/**\n * sse-transport.ts\n *\n * SignalR transport using Server-Sent Events (SSE) for receiving and\n * HTTP POST for sending.\n *\n * SSE spec: https://html.spec.whatwg.org/multipage/server-sent-events.html\n *\n * Updated to use the new StreamResult shape from http-client.ts:\n * result.body - Node Readable carrying the SSE byte stream\n * result.abort - cancels the in-flight request (replaces req.destroy())\n */\n\nimport type { IHttpClient } from '../interfaces.js';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\n\nexport class ServerSentEventsTransport implements ITransport {\n readonly name = 'ServerSentEvents' as const;\n\n readonly #httpClient: IHttpClient;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n\n #url: string | null = null;\n #abort: (() => void) | null = null; // replaces the old ClientRequest handle\n #sseBuffer: string = '';\n\n onreceive: ((data: string | Uint8Array) => void) | null = null;\n onclose: ((error?: Error) => void) | null = null;\n\n constructor(\n httpClient: IHttpClient,\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n ) {\n this.#httpClient = httpClient;\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n }\n\n async connect(url: string, transferFormat: TransferFormat): Promise<void> {\n if (transferFormat === TransferFormat.Binary) {\n throw new Error('The Server-Sent Events transport only supports the Text transfer format.');\n }\n\n this.#logger.log(LogLevel.Trace, `(SSE transport) Connecting to ${url}.`);\n this.#url = url;\n\n const headers: Record<string, string> = {\n Accept: 'text/event-stream',\n ...this.#extraHeaders,\n };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const result = await this.#httpClient.stream('GET', url, { headers });\n\n if (result.statusCode !== 200) {\n // Attach a no-op error handler before destroying the body to prevent an\n // unhandled 'error' event if the underlying stream emits one on abort.\n result.body.on('error', () => {});\n result.abort();\n throw new Error(\n `Unexpected status code ${result.statusCode} from SSE endpoint.`,\n );\n }\n\n // Store the abort handle so stop() can cancel the long-lived GET\n this.#abort = result.abort;\n\n // The body is a Node Readable; setEncoding converts chunks to strings\n result.body.setEncoding('utf8');\n\n result.body.on('data', (chunk: string) => this.#onData(chunk));\n result.body.on('end', () => {\n this.#logger.log(LogLevel.Information, '(SSE transport) EventSource closed.');\n this.#abort = null;\n this.onclose?.();\n });\n result.body.on('error', (err: Error) => {\n this.#logger.log(LogLevel.Error, `(SSE transport) Stream error: ${err.message}`);\n this.#abort = null;\n this.onclose?.(err);\n });\n\n this.#logger.log(LogLevel.Information, '(SSE transport) Connected.');\n }\n\n async send(data: string | Uint8Array): Promise<void> {\n if (!this.#url) throw new Error('SSE transport is not connected.');\n\n const headers: Record<string, string> = {\n 'Content-Type': typeof data === 'string'\n ? 'text/plain;charset=UTF-8'\n : 'application/octet-stream',\n ...this.#extraHeaders,\n };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const body = typeof data === 'string' ? data : Buffer.from(data).toString('binary');\n const result = await this.#httpClient.post(this.#url, { headers, body });\n\n if (result.status < 200 || result.status >= 300) {\n throw new Error(`SSE send failed with status ${result.status}.`);\n }\n }\n\n stop(): Promise<void> {\n if (this.#abort) {\n this.#abort();\n this.#abort = null;\n }\n return Promise.resolve();\n }\n\n // ─── SSE parser ───────────────────────────────────────────────────────────\n\n #onData(chunk: string): void {\n this.#sseBuffer += chunk;\n\n let boundary: number;\n while ((boundary = findEventBoundary(this.#sseBuffer)) !== -1) {\n const block = this.#sseBuffer.slice(0, boundary);\n this.#sseBuffer = this.#sseBuffer.slice(boundary).replace(/^[\\r\\n]+/, '');\n this.#dispatchEvent(block);\n }\n }\n\n #dispatchEvent(block: string): void {\n const lines = block.split(/\\r?\\n/);\n const dataParts: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n dataParts.push(line.slice(5).replace(/^ /, ''));\n }\n // event:, id:, retry: are intentionally ignored by SignalR's SSE\n }\n\n if (dataParts.length === 0) return;\n\n const message = dataParts.join('\\n');\n this.#logger.log(LogLevel.Trace, `(SSE transport) Received data: ${message}`);\n this.onreceive?.(message);\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction findEventBoundary(str: string): number {\n const i1 = str.indexOf('\\n\\n');\n const i2 = str.indexOf('\\r\\n\\r\\n');\n if (i1 === -1 && i2 === -1) return -1;\n if (i1 === -1) return i2 + 4;\n if (i2 === -1) return i1 + 2;\n return Math.min(i1 + 2, i2 + 4);\n}\n","/**\n * long-polling-transport.ts\n *\n * SignalR Long-Polling transport.\n * HTTP GET (hangs until data arrives) → receive\n * HTTP POST → send\n * HTTP DELETE → disconnect\n *\n * Updated to depend on IHttpClient rather than the concrete HttpClient class\n * so any of the five undici-backed client implementations can be injected.\n */\n\nimport type { IHttpClient } from '../interfaces.js';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\n\n/** How long a single poll GET can hang before we issue a new one. */\nconst POLL_TIMEOUT_MS = 100_000;\n\nexport class LongPollingTransport implements ITransport {\n readonly name = 'LongPolling' as const;\n\n readonly #httpClient: IHttpClient;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n\n #url: string | null = null;\n #running: boolean = false;\n #pollImmediate: ReturnType<typeof setImmediate> | null = null;\n\n onreceive: ((data: string | Uint8Array) => void) | null = null;\n onclose: ((error?: Error) => void) | null = null;\n\n constructor(\n httpClient: IHttpClient,\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n ) {\n this.#httpClient = httpClient;\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n }\n\n async connect(url: string, _transferFormat: TransferFormat): Promise<void> {\n this.#logger.log(LogLevel.Trace, `(LongPolling transport) Connecting to ${url}.`);\n this.#url = url;\n this.#running = true;\n\n // Validate the connection with an initial poll\n await this.#poll(url, /* isConnect */ true);\n\n // Start the background poll loop\n this.#schedulePoll();\n this.#logger.log(LogLevel.Information, '(LongPolling transport) Connected.');\n }\n\n async send(data: string | Uint8Array): Promise<void> {\n if (!this.#running || !this.#url) {\n throw new Error('LongPolling transport is not connected.');\n }\n\n const headers = await this.#buildHeaders({\n 'Content-Type': typeof data === 'string'\n ? 'text/plain;charset=UTF-8'\n : 'application/octet-stream',\n });\n\n const body = typeof data === 'string' ? data : Buffer.from(data).toString('binary');\n const result = await this.#httpClient.post(this.#url, { headers, body });\n\n if (result.status < 200 || result.status >= 300) {\n throw new Error(`Long polling send failed with status ${result.status}.`);\n }\n }\n\n async stop(): Promise<void> {\n this.#running = false;\n\n if (this.#pollImmediate !== null) {\n clearImmediate(this.#pollImmediate);\n this.#pollImmediate = null;\n }\n\n if (this.#url) {\n try {\n const headers = await this.#buildHeaders();\n await this.#httpClient.delete(this.#url, { headers });\n } catch (e) {\n this.#logger.log(\n LogLevel.Warning,\n `(LongPolling transport) Error sending DELETE: ${(e as Error).message}`,\n );\n }\n }\n }\n\n // ─── Internal polling ─────────────────────────────────────────────────────\n\n #schedulePoll(): void {\n if (!this.#running) return;\n this.#pollImmediate = setImmediate(() => void this.#pollLoop());\n }\n\n async #pollLoop(): Promise<void> {\n /* istanbul ignore next - #schedulePoll()'s !#running guard and\n clearImmediate() in stop() together prevent #pollLoop from ever\n being called once the transport has stopped; this is a\n belt-and-suspenders defence. */\n if (!this.#running || !this.#url) return;\n try {\n await this.#poll(this.#url, /* isConnect */ false);\n } catch (err) {\n /* istanbul ignore else - between #poll re-throwing and this catch,\n no macrotask can run to set #running=false; the false branch is\n a belt-and-suspenders defence against a theoretical race. */\n if (this.#running) {\n this.#logger.log(\n LogLevel.Error,\n `(LongPolling transport) Poll error: ${(err as Error).message}`,\n );\n this.#running = false;\n this.onclose?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n }\n this.#schedulePoll();\n }\n\n async #poll(url: string, isConnect: boolean): Promise<void> {\n const headers = await this.#buildHeaders();\n\n let res;\n try {\n res = await this.#httpClient.get(url, { headers, timeout: POLL_TIMEOUT_MS });\n } catch (err) {\n if (!this.#running) return; // normal stop - swallow\n throw err;\n }\n\n if (res.status === 204) {\n // Server ended connection gracefully\n this.#logger.log(LogLevel.Information, '(LongPolling transport) Server closed (204).');\n this.#running = false;\n this.onclose?.();\n return;\n }\n\n if (res.status < 200 || res.status >= 300) {\n const err = new Error(`Long polling received unexpected status ${res.status}.`);\n if (!isConnect) {\n this.#running = false;\n this.onclose?.(err);\n } else {\n throw err;\n }\n return;\n }\n\n if (res.body.length > 0) {\n this.#logger.log(LogLevel.Trace, `(LongPolling transport) Received: ${res.body}`);\n this.onreceive?.(res.body);\n }\n }\n\n async #buildHeaders(extra: Record<string, string> = {}): Promise<Record<string, string>> {\n const headers: Record<string, string> = { ...this.#extraHeaders, ...extra };\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n return headers;\n }\n}\n","/**\n * logger.ts\n *\n * Built-in ILogger implementations.\n * ConsoleLogger - writes to console with timestamps and severity labels.\n * NullLogger - discards everything (default when no logger is configured).\n */\n\nimport { LogLevel } from './constants.js';\nimport type { ILogger } from './interfaces.js';\n\n// ─── ConsoleLogger ────────────────────────────────────────────────────────────\n\nexport class ConsoleLogger implements ILogger {\n readonly #minimumLevel: LogLevel;\n\n constructor(minimumLevel: LogLevel = LogLevel.Information) {\n this.#minimumLevel = minimumLevel;\n }\n\n log(level: LogLevel, message: string): void {\n if (level < this.#minimumLevel) return;\n\n const ts = new Date().toISOString();\n const label = logLevelName(level);\n const line = `[${ts}] [${label}] ${message}`;\n\n switch (level) {\n case LogLevel.Trace:\n case LogLevel.Debug:\n console.debug(line);\n break;\n case LogLevel.Warning:\n console.warn(line);\n break;\n case LogLevel.Error:\n case LogLevel.Critical:\n console.error(line);\n break;\n default:\n console.log(line);\n break;\n }\n }\n}\n\n// ─── NullLogger ───────────────────────────────────────────────────────────────\n\nexport class NullLogger implements ILogger {\n /** Singleton - no state, so one instance is enough. */\n static readonly instance: NullLogger = new NullLogger();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n log(_logLevel: LogLevel, _message: string): void {\n // intentionally empty\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Reverse-map a LogLevel number to its string label. */\nfunction logLevelName(level: LogLevel): string {\n const entry = (Object.entries(LogLevel) as [string, LogLevel][]).find(\n ([, v]) => v === level\n );\n return entry?.[0] ?? String(level);\n}\n\n/** Normalise a LogLevel number or ILogger into an ILogger. */\nexport function resolveLogger(logLevelOrLogger: LogLevel | ILogger): ILogger {\n if (typeof logLevelOrLogger === 'number') {\n return new ConsoleLogger(logLevelOrLogger);\n }\n if (\n logLevelOrLogger != null &&\n typeof logLevelOrLogger === 'object' &&\n typeof (logLevelOrLogger as ILogger).log === 'function'\n ) {\n return logLevelOrLogger as ILogger;\n }\n throw new TypeError(\n 'configureLogging expects a LogLevel number or an object with a log(level, message) method.'\n );\n}\n","/**\n * errors.ts\n *\n * Typed error classes for the SignalR client. Each has a distinct `name`\n * so callers can use `instanceof` or switch on `error.name` to distinguish\n * error categories at runtime.\n */\n\n// ─── Base ────────────────────────────────────────────────────────────────────\n\n/** Thrown when a hub method invocation fails with a server-side error. */\nexport class HubError extends Error {\n override readonly name = 'HubError' as const;\n\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an in-flight operation is cancelled (e.g. connection closed). */\nexport class AbortError extends Error {\n override readonly name = 'AbortError' as const;\n\n constructor(message = 'The operation was aborted.') {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown on network-level transport failures. */\nexport class TransportError extends Error {\n override readonly name = 'TransportError' as const;\n readonly statusCode: number | undefined;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when the SignalR protocol handshake is rejected by the server. */\nexport class HandshakeError extends Error {\n override readonly name = 'HandshakeError' as const;\n\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when no acceptable transport could be negotiated. */\nexport class UnsupportedTransportError extends Error {\n override readonly name = 'UnsupportedTransportError' as const;\n readonly transport: number | null;\n\n constructor(message: string, transport: number | null) {\n super(message);\n this.transport = transport;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown internally when negotiate returns an Azure SignalR redirect.\n * Handled transparently by HubConnection - not exposed to callers.\n * @internal\n */\nexport class RedirectError extends Error {\n override readonly name = 'RedirectError' as const;\n readonly url: string;\n readonly accessToken: string | undefined;\n\n constructor(url: string, accessToken?: string) {\n super(`Redirected to ${url}`);\n this.url = url;\n this.accessToken = accessToken;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ─── Type guard helpers ───────────────────────────────────────────────────────\n\nexport function isHubError(e: unknown): e is HubError {\n return e instanceof HubError;\n}\n\nexport function isAbortError(e: unknown): e is AbortError {\n return e instanceof AbortError;\n}\n\nexport function isTransportError(e: unknown): e is TransportError {\n return e instanceof TransportError;\n}\n","/**\n * hub-connection.ts\n *\n * Core HubConnection - the main object users interact with.\n *\n * Mirrors the Microsoft SignalR JavaScript client API with full TypeScript types:\n * start() / stop()\n * invoke<T>(method, ...args) → Promise<T>\n * send(method, ...args) → Promise<void>\n * stream<T>(method, ...args) → IStreamResult<T>\n * on(method, handler)\n * off(method, [handler])\n * onclose / onreconnecting / onreconnected\n */\n\nimport { DispatchHttpClient } from './http-client.js';\nimport {\n JsonHubProtocol,\n HANDSHAKE_REQUEST,\n parseHandshakeResponse,\n} from './protocols/json-hub-protocol.js';\nimport { WebSocketTransport } from './transports/websocket-transport.js';\nimport { ServerSentEventsTransport } from './transports/sse-transport.js';\nimport { LongPollingTransport } from './transports/long-polling-transport.js';\nimport { NullLogger } from './logger.js';\nimport {\n MessageType,\n HubConnectionState,\n HttpTransportType,\n TransferFormat,\n LogLevel,\n NEGOTIATE_VERSION,\n DEFAULT_PING_INTERVAL_IN_MS,\n DEFAULT_SERVER_TIMEOUT_IN_MS,\n} from './constants.js';\nimport {\n HubError,\n AbortError,\n TransportError,\n UnsupportedTransportError,\n} from './errors.js';\nimport type {\n ITransport,\n ILogger,\n IHttpClient,\n IRetryPolicy,\n RetryContext,\n IStreamResult,\n IStreamSubscriber,\n ISubscription,\n NegotiateResponse,\n Dispatcher,\n} from './interfaces.js';\nimport type { InvocationId } from './messages.js';\nimport { toInvocationId } from './messages.js';\n\nconst MAX_REDIRECTS = 100;\n\n// ─── Configuration ────────────────────────────────────────────────────────────\n\nexport interface HubConnectionOptions {\n readonly logger?: ILogger;\n readonly accessTokenFactory?: () => Promise<string | null>;\n /** Bitmask of HttpTransportType flags (default: all transports). */\n readonly transport?: number;\n readonly headers?: Record<string, string>;\n readonly skipNegotiation?: boolean;\n readonly serverTimeoutInMilliseconds?: number;\n readonly keepAliveIntervalInMilliseconds?: number;\n /**\n * Override the SignalR handshake timeout (ms). Defaults to 15 000.\n * Intended for testing; production code should leave this at the default.\n */\n readonly handshakeTimeoutInMilliseconds?: number;\n readonly reconnectPolicy?: IRetryPolicy | null;\n /**\n * undici Dispatcher shared by all HTTP requests (negotiate, SSE, polling)\n * and the WebSocket upgrade for this connection.\n *\n * Pass an `Agent`, `Pool`, `Client`, `ProxyAgent`, etc. to customise\n * connection pooling, TLS, or proxy routing for the entire SignalR session.\n * When omitted, undici's process-global default agent is used.\n */\n readonly dispatcher?: Dispatcher;\n /**\n * Custom HTTP client to use for all requests made by this connection\n * (negotiate, SSE body reads, long-polling).\n *\n * When omitted, a `DispatchHttpClient` is created automatically using\n * the `dispatcher` option (if any). Provide this to use a different\n * undici primitive (e.g. `FetchHttpClient`) or to inject a mock in tests.\n */\n readonly httpClient?: IHttpClient;\n}\n\n// ─── Internal pending-invocation tracking ────────────────────────────────────\n\ninterface PendingInvocation<T = unknown> {\n resolve: (value: T) => void;\n reject: (err: Error) => void;\n}\n\ninterface PendingStream<T = unknown> {\n next: (value: T) => void;\n error: (err: Error) => void;\n complete: () => void;\n}\n\n// ─── Subscription (supports `using` keyword via Symbol.dispose) ───────────────\n\nclass StreamSubscription implements ISubscription {\n #disposed = false;\n readonly #cancel: () => void;\n\n constructor(cancel: () => void) {\n this.#cancel = cancel;\n }\n\n dispose(): void {\n if (!this.#disposed) {\n this.#disposed = true;\n this.#cancel();\n }\n }\n\n /** TS 5.2+ `using` keyword support. */\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// ─── HubConnection ────────────────────────────────────────────────────────────\n\nexport class HubConnection {\n readonly #url: string;\n readonly #logger: ILogger;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #requestedTransport: number;\n readonly #extraHeaders: Record<string, string>;\n readonly #skipNegotiation: boolean;\n readonly #serverTimeout: number;\n readonly #pingInterval: number;\n readonly #handshakeTimeout: number;\n readonly #reconnectPolicy: IRetryPolicy | null;\n\n readonly #protocol: JsonHubProtocol;\n readonly #http: IHttpClient;\n readonly #dispatcher: Dispatcher | undefined;\n\n #transport: ITransport | null = null;\n #connectionId: string | null = null;\n #connectionToken: string | null = null;\n #state: HubConnectionState = HubConnectionState.Disconnected;\n #stopping: boolean = false;\n\n /** Pending `invoke()` calls awaiting a Completion message. */\n readonly #callbacks: Map<InvocationId, PendingInvocation> = new Map();\n /** Active server-streaming subscriptions awaiting StreamItem/Completion. */\n readonly #streamCbs: Map<InvocationId, PendingStream> = new Map();\n /** Client-method handlers registered via `on()`. */\n readonly #methods: Map<string, Set<(...args: unknown[]) => void>> = new Map();\n\n /** Registered `onclose` callbacks. */\n readonly #closedCallbacks: Array<(error?: Error) => void> = [];\n /** Registered `onreconnecting` callbacks. */\n readonly #reconnectingCallbacks: Array<(error?: Error) => void> = [];\n /** Registered `onreconnected` callbacks. */\n readonly #reconnectedCallbacks: Array<(connectionId: string | null) => void> = [];\n\n #pingTimer: ReturnType<typeof setTimeout> | null = null;\n #serverTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n #handshakeTimer: ReturnType<typeof setTimeout> | null = null;\n\n #handshakeResolver: (() => void) | null = null;\n #handshakeRejecter: ((e: Error) => void) | null = null;\n\n #messageBuffer: string = '';\n #invocationSeq: number = 0;\n\n constructor(url: string, options: HubConnectionOptions = {}) {\n this.#url = url;\n this.#logger = options.logger ?? NullLogger.instance;\n this.#accessTokenFactory = options.accessTokenFactory ?? null;\n this.#requestedTransport = options.transport\n ?? (HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling);\n this.#extraHeaders = options.headers ?? {};\n this.#skipNegotiation = options.skipNegotiation ?? false;\n this.#serverTimeout = options.serverTimeoutInMilliseconds ?? DEFAULT_SERVER_TIMEOUT_IN_MS;\n this.#pingInterval = options.keepAliveIntervalInMilliseconds ?? DEFAULT_PING_INTERVAL_IN_MS;\n this.#handshakeTimeout = options.handshakeTimeoutInMilliseconds ?? 15_000;\n this.#reconnectPolicy = options.reconnectPolicy ?? null;\n this.#protocol = new JsonHubProtocol();\n this.#dispatcher = options.dispatcher;\n // Use the caller-supplied client, or create a DispatchHttpClient that shares\n // the same dispatcher so negotiate + polls + WebSocket all use one pool.\n this.#http = options.httpClient\n ?? new DispatchHttpClient({\n headers: this.#extraHeaders,\n ...(options.dispatcher !== undefined && { dispatcher: options.dispatcher }),\n });\n }\n\n // ─── State ───────────────────────────────────────────────────────────────\n\n get state(): HubConnectionState { return this.#state; }\n get connectionId(): string | null { return this.#connectionId; }\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n async start(): Promise<void> {\n if (this.#state !== HubConnectionState.Disconnected) {\n throw new Error(\n `Cannot start: connection is not Disconnected (current: ${this.#state}).`\n );\n }\n this.#state = HubConnectionState.Connecting;\n this.#stopping = false;\n this.#logger.log(LogLevel.Debug, 'Starting HubConnection.');\n\n try {\n await this.#startInternal();\n this.#state = HubConnectionState.Connected;\n this.#logger.log(LogLevel.Information, 'HubConnection connected.');\n } catch (err) {\n this.#state = HubConnectionState.Disconnected;\n this.#logger.log(LogLevel.Error, `Failed to start: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async stop(): Promise<void> {\n this.#stopping = true;\n this.#logger.log(LogLevel.Debug, 'Stopping HubConnection.');\n this.#clearTimers();\n\n const stopErr = new AbortError('Connection stopped before the invocation completed.');\n this.#rejectAllPending(stopErr);\n\n if (this.#transport) {\n try { await this.#transport.stop(); } catch { /* ignore */ }\n this.#transport = null;\n }\n\n this.#state = HubConnectionState.Disconnected;\n this.#logger.log(LogLevel.Information, 'HubConnection stopped.');\n }\n\n // ─── Sending ─────────────────────────────────────────────────────────────\n\n /**\n * Invoke a hub method and return the server's result.\n *\n * @typeParam T The expected return type. Asserted at runtime - the server\n * decides the actual value.\n */\n invoke<T = void>(methodName: string, ...args: unknown[]): Promise<T> {\n this.#assertConnected('invoke');\n const id = this.#nextId();\n const msg = this.#protocol.writeMessage(\n JsonHubProtocol.invocation(id, methodName, args)\n ) as string;\n\n return new Promise<T>((resolve, reject) => {\n this.#callbacks.set(id, {\n resolve: resolve as (v: unknown) => void,\n reject,\n });\n this.#send(msg).catch((err: Error) => {\n this.#callbacks.delete(id);\n reject(err);\n });\n });\n }\n\n /**\n * Fire-and-forget hub method invocation.\n * The server does not send a completion message.\n */\n send(methodName: string, ...args: unknown[]): Promise<void> {\n this.#assertConnected('send');\n const msg = this.#protocol.writeMessage(\n JsonHubProtocol.send(methodName, args)\n ) as string;\n return this.#send(msg);\n }\n\n // ─── Server-streaming ────────────────────────────────────────────────────\n\n /**\n * Start a server-streaming invocation.\n * The call is not sent until `subscribe` is called.\n * The returned `ISubscription` implements `Symbol.dispose` for `using`.\n *\n * @typeParam T Type of each streamed item.\n *\n * @example\n * ```ts\n * using sub = connection.stream<number>('Counter', 10).subscribe({\n * next: (n) => console.log(n),\n * complete: () => console.log('done'),\n * });\n * ```\n */\n stream<T = unknown>(methodName: string, ...args: unknown[]): IStreamResult<T> {\n this.#assertConnected('stream');\n const id = this.#nextId();\n\n return {\n subscribe: (subscriber: IStreamSubscriber<T>): ISubscription => {\n const msg = this.#protocol.writeMessage(\n JsonHubProtocol.streamInvocation(id, methodName, args)\n ) as string;\n\n this.#streamCbs.set(id, {\n next: (v) => subscriber.next?.(v as T),\n error: (e) => subscriber.error?.(e),\n complete: () => subscriber.complete?.(),\n });\n\n this.#send(msg).catch((err: Error) => {\n this.#streamCbs.delete(id);\n subscriber.error?.(err);\n });\n\n return new StreamSubscription(() => {\n if (this.#streamCbs.has(id)) {\n this.#streamCbs.delete(id);\n this.#send(\n this.#protocol.writeMessage(JsonHubProtocol.cancelInvocation(id)) as string\n ).catch(() => { /* best-effort */ });\n }\n });\n },\n };\n }\n\n // ─── Event registration ───────────────────────────────────────────────────\n\n /**\n * Register a handler for a server→client hub method.\n * Multiple handlers for the same method are supported.\n *\n * @typeParam TArgs Tuple of argument types for the hub method.\n */\n on<TArgs extends unknown[] = unknown[]>(\n methodName: string,\n handler: (...args: TArgs) => void,\n ): void {\n const key = methodName.toLowerCase();\n if (!this.#methods.has(key)) this.#methods.set(key, new Set());\n this.#methods.get(key)!.add(handler as (...args: unknown[]) => void);\n }\n\n /**\n * Remove a previously registered handler, or all handlers for a method.\n */\n off(methodName: string, handler?: (...args: unknown[]) => void): void {\n const key = methodName.toLowerCase();\n if (!this.#methods.has(key)) return;\n if (handler == null) {\n this.#methods.delete(key);\n } else {\n this.#methods.get(key)!.delete(handler);\n if (this.#methods.get(key)!.size === 0) this.#methods.delete(key);\n }\n }\n\n onclose(callback: (error?: Error) => void): void { this.#closedCallbacks.push(callback); }\n onreconnecting(callback:(error?: Error) => void): void { this.#reconnectingCallbacks.push(callback); }\n onreconnected(callback: (connectionId: string | null) => void): void { this.#reconnectedCallbacks.push(callback); }\n\n // ─── Internal: start sequence ────────────────────────────────────────────\n\n async #startInternal(): Promise<void> {\n let url = this.#url;\n\n if (this.#skipNegotiation) {\n if ((this.#requestedTransport & HttpTransportType.WebSockets) === 0) {\n throw new Error('skipNegotiation requires the WebSockets transport.');\n }\n this.#transport = this.#createTransport(HttpTransportType.WebSockets);\n await this.#connectTransport(url, TransferFormat.Text);\n } else {\n let redirectCount = 0;\n for (;;) {\n const neg = await this.#negotiate(url);\n\n if (neg.url) {\n if (redirectCount++ >= MAX_REDIRECTS) throw new Error('Too many negotiate redirects.');\n url = neg.url;\n if (neg.accessToken) {\n const staticToken = neg.accessToken;\n this.#overrideAccessToken(() => Promise.resolve(staticToken));\n }\n continue;\n }\n\n this.#connectionId = neg.connectionId ?? null;\n this.#connectionToken = neg.connectionToken ?? neg.connectionId ?? null;\n\n await this.#selectTransport(url, neg.availableTransports ?? []);\n break;\n }\n }\n\n // Wire message routing\n this.#transport!.onreceive = (data) => this.#processIncoming(\n typeof data === 'string' ? data : Buffer.from(data).toString('utf8')\n );\n this.#transport!.onclose = (err) => this.#onTransportClosed(err);\n\n // Protocol handshake\n await this.#performHandshake();\n\n // Keep-alive\n this.#resetPingTimer();\n this.#resetServerTimeoutTimer();\n }\n\n // Rebinds the access token factory (used after Azure SignalR redirect).\n // Stored as a field to allow rebinding without recreating the instance.\n #_accessTokenFactory: (() => Promise<string | null>) | null = null;\n\n #overrideAccessToken(factory: () => Promise<string | null>): void {\n this.#_accessTokenFactory = factory;\n }\n\n #getAccessTokenFactory(): (() => Promise<string | null>) | null {\n return this.#_accessTokenFactory ?? this.#accessTokenFactory;\n }\n\n async #negotiate(baseUrl: string): Promise<NegotiateResponse> {\n // Use the URL API so that an existing query string in baseUrl (e.g.\n // \"?token=abc\") does not corrupt the pathname. Simple string concatenation\n // would produce \"?token=abc/negotiate\" - wrong path, wrong query string.\n const negotiateUrl = new URL(baseUrl);\n negotiateUrl.pathname = negotiateUrl.pathname.replace(/\\/$/, '') + '/negotiate';\n negotiateUrl.searchParams.set('negotiateVersion', String(NEGOTIATE_VERSION));\n const url = negotiateUrl.toString();\n this.#logger.log(LogLevel.Debug, `Sending negotiate request to ${url}.`);\n\n const headers: Record<string, string> = { ...this.#extraHeaders };\n const factory = this.#getAccessTokenFactory();\n if (factory) {\n const token = await factory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const res = await this.#http.post(url, { headers });\n\n if (res.status !== 200) {\n throw new TransportError(\n `Unexpected status code ${res.status} from negotiate.`,\n res.status\n );\n }\n\n const body = JSON.parse(res.body) as NegotiateResponse;\n if (body.error) throw new Error(`Negotiate returned error: ${body.error}`);\n return body;\n }\n\n async #selectTransport(\n url: string,\n available: readonly { transport: string; transferFormats: readonly string[] }[],\n ): Promise<void> {\n const ORDERED = [\n { flag: HttpTransportType.WebSockets, name: 'WebSockets', format: TransferFormat.Text },\n { flag: HttpTransportType.ServerSentEvents, name: 'ServerSentEvents', format: TransferFormat.Text },\n { flag: HttpTransportType.LongPolling, name: 'LongPolling', format: TransferFormat.Text },\n ] as const;\n\n const serverSet = new Set(available.map((t) => t.transport));\n\n for (const pref of ORDERED) {\n if ((this.#requestedTransport & pref.flag) === 0) continue;\n if (!serverSet.has(pref.name)) continue;\n\n this.#logger.log(LogLevel.Debug, `Trying ${pref.name} transport.`);\n const transport = this.#createTransport(pref.flag);\n const token = this.#connectionToken ?? '';\n const tUrl = appendParam(url, 'id', token);\n\n try {\n await transport.connect(tUrl, pref.format);\n this.#transport = transport;\n return;\n } catch (err) {\n this.#logger.log(LogLevel.Warning, `${pref.name} failed: ${(err as Error).message}`);\n }\n }\n\n throw new UnsupportedTransportError(\n 'Unable to connect with any of the available transports.',\n null\n );\n }\n\n async #connectTransport(url: string, format: TransferFormat): Promise<void> {\n await this.#transport!.connect(url, format);\n }\n\n #createTransport(type: number): ITransport {\n const factory = this.#getAccessTokenFactory();\n const headers = this.#extraHeaders;\n switch (type) {\n case HttpTransportType.WebSockets:\n return new WebSocketTransport(factory, this.#logger, headers, this.#dispatcher);\n case HttpTransportType.ServerSentEvents:\n return new ServerSentEventsTransport(this.#http, factory, this.#logger, headers);\n case HttpTransportType.LongPolling:\n return new LongPollingTransport(this.#http, factory, this.#logger, headers);\n /* istanbul ignore next */\n default:\n throw new UnsupportedTransportError(`Unknown transport type: ${type}`, type);\n }\n }\n\n // ─── Internal: handshake ─────────────────────────────────────────────────\n\n #performHandshake(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.#handshakeResolver = resolve;\n this.#handshakeRejecter = reject;\n\n this.#transport!.send(HANDSHAKE_REQUEST).catch(reject);\n\n this.#handshakeTimer = setTimeout(() => {\n reject(new Error('Server timeout: no handshake response received.'));\n }, this.#handshakeTimeout);\n });\n }\n\n // ─── Internal: incoming data ─────────────────────────────────────────────\n\n #processIncoming(text: string): void {\n this.#resetServerTimeoutTimer();\n this.#messageBuffer += text;\n\n // During handshake the first data is the response\n if (this.#handshakeResolver) {\n try {\n const { remainder } = parseHandshakeResponse(this.#messageBuffer);\n this.#messageBuffer = remainder;\n this.#logger.log(LogLevel.Debug, 'Handshake complete.');\n clearTimeout(this.#handshakeTimer!);\n const r = this.#handshakeResolver;\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n r();\n } catch (err) {\n clearTimeout(this.#handshakeTimer!);\n const r = this.#handshakeRejecter!;\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n r(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n }\n\n if (!this.#messageBuffer) return;\n\n let messages;\n try {\n messages = this.#protocol.parseMessages(this.#messageBuffer, this.#logger);\n } catch (err) {\n this.#logger.log(LogLevel.Error, `Error parsing messages: ${(err as Error).message}`);\n this.#stopWithError(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n\n // Every complete record was consumed by parseMessages; the buffer is now empty\n this.#messageBuffer = '';\n\n for (const msg of messages) {\n switch (msg.type) {\n // ── Type 1: Server calls a client method ──────────────────────────\n case MessageType.Invocation: {\n const key = msg.target.toLowerCase();\n const handlers = this.#methods.get(key);\n if (!handlers || handlers.size === 0) {\n this.#logger.log(LogLevel.Warning, `No handler for \"${msg.target}\".`);\n break;\n }\n for (const h of handlers) {\n try { h(...(msg.arguments as unknown[])); }\n catch (e) {\n this.#logger.log(LogLevel.Error, `Handler for \"${msg.target}\" threw: ${(e as Error).message}`);\n }\n }\n break;\n }\n\n // ── Type 2: One item from a server stream ─────────────────────────\n // Per spec, StreamItem carries only `item`; there is no `error` field.\n case MessageType.StreamItem: {\n const sc = this.#streamCbs.get(msg.invocationId);\n if (!sc) break;\n sc.next(msg.item);\n break;\n }\n\n // ── Type 3: Completion of an invoke() or stream ───────────────────\n case MessageType.Completion: {\n const cb = this.#callbacks.get(msg.invocationId);\n if (cb) {\n this.#callbacks.delete(msg.invocationId);\n if (msg.error) cb.reject(new HubError(msg.error));\n else cb.resolve(msg.result ?? null);\n }\n const sc = this.#streamCbs.get(msg.invocationId);\n if (sc) {\n this.#streamCbs.delete(msg.invocationId);\n if (msg.error) sc.error(new HubError(msg.error));\n else sc.complete();\n }\n break;\n }\n\n // ── Type 6: Ping ──────────────────────────────────────────────────\n case MessageType.Ping:\n // Server-timeout watchdog already reset at the top of this method\n break;\n\n // ── Type 7: Server-initiated close ────────────────────────────────\n case MessageType.Close: {\n this.#logger.log(LogLevel.Information, 'Server sent Close message.');\n const closeErr = msg.error ? new HubError(msg.error) : null;\n // Per spec: if allowReconnect is true AND the client has a reconnect\n // policy, the client should attempt reconnection rather than a\n // permanent disconnect. Null out onclose on the old transport to\n // prevent #onTransportClosed from firing a second reconnect loop.\n if (msg.allowReconnect && this.#reconnectPolicy && !this.#stopping) {\n this.#clearTimers();\n /* istanbul ignore next - #transport is always non-null here; null\n is a defensive guard against theoretical concurrent nulling. */\n if (this.#transport) this.#transport.onclose = null;\n const t = this.#transport;\n this.#transport = null;\n void t?.stop().catch(() => {});\n void this.#doReconnect(closeErr);\n } else {\n this.#stopWithError(closeErr);\n }\n break;\n }\n\n default:\n this.#logger.log(LogLevel.Warning, `Unknown message type: ${(msg as { type: number }).type}`);\n break;\n }\n }\n }\n\n // ─── Internal: transport closed ──────────────────────────────────────────\n\n #onTransportClosed(err?: Error): void {\n /* istanbul ignore next - WebSocketTransport.stop() nulls #ws before\n calling ws.close(), so the close handler never invokes onclose once\n stop() has set #stopping; this guard is a belt-and-suspenders defence. */\n if (this.#stopping) return;\n this.#logger.log(\n LogLevel.Warning,\n err ? `Transport closed with error: ${err.message}` : 'Transport closed.'\n );\n this.#clearTimers();\n\n if (this.#reconnectPolicy) {\n void this.#doReconnect(err ?? null);\n } else {\n this.#completeClose(err);\n }\n }\n\n #stopWithError(err: Error | null): void {\n this.#clearTimers();\n void this.#transport?.stop().catch(() => { /* ignore */ });\n this.#transport = null;\n this.#completeClose(err ?? undefined);\n }\n\n #completeClose(err?: Error): void {\n const closeErr = err ?? new AbortError('Connection closed.');\n this.#rejectAllPending(closeErr);\n this.#state = HubConnectionState.Disconnected;\n for (const cb of this.#closedCallbacks) {\n try { cb(err); } catch { /* ignore */ }\n }\n }\n\n #rejectAllPending(err: Error): void {\n this.#callbacks.forEach((cb) => cb.reject(err));\n this.#callbacks.clear();\n this.#streamCbs.forEach((sc) => sc.error(err));\n this.#streamCbs.clear();\n }\n\n // ─── Internal: auto-reconnect ─────────────────────────────────────────────\n\n async #doReconnect(disconnectError: Error | null): Promise<void> {\n this.#state = HubConnectionState.Reconnecting;\n for (const cb of this.#reconnectingCallbacks) {\n try { cb(disconnectError ?? undefined); } catch { /* ignore */ }\n }\n\n let retryCount = 0;\n const startTime = Date.now();\n let lastError = disconnectError;\n\n while (!this.#stopping) {\n const ctx: RetryContext = {\n previousRetryCount: retryCount,\n elapsedMilliseconds: Date.now() - startTime,\n retryReason: lastError,\n };\n const delay = this.#reconnectPolicy!.nextRetryDelayInMilliseconds(ctx);\n if (delay === null) {\n this.#logger.log(LogLevel.Debug, 'Reconnect policy returned null - giving up.');\n break;\n }\n\n this.#logger.log(LogLevel.Information, `Reconnecting in ${delay} ms (attempt ${retryCount + 1}).`);\n await sleep(delay);\n if (this.#stopping) break;\n\n try {\n await this.#startInternal();\n this.#state = HubConnectionState.Connected;\n this.#logger.log(LogLevel.Information, 'Reconnected successfully.');\n for (const cb of this.#reconnectedCallbacks) {\n try { cb(this.#connectionId); } catch { /* ignore */ }\n }\n return;\n } catch (err) {\n retryCount++;\n /* istanbul ignore next - #startInternal() only throws Error instances. */\n lastError = err instanceof Error ? err : new Error(String(err));\n this.#logger.log(LogLevel.Warning, `Reconnect attempt ${retryCount} failed: ${lastError.message}`);\n }\n }\n\n this.#completeClose(lastError ?? undefined);\n }\n\n // ─── Internal: timers ────────────────────────────────────────────────────\n\n #resetPingTimer(): void {\n clearTimeout(this.#pingTimer!);\n this.#pingTimer = setTimeout(async () => {\n /* istanbul ignore next - #clearTimers() always cancels this before state\n leaves Connected; the guard is a defensive fallback. */\n if (this.#state !== HubConnectionState.Connected) return;\n try {\n await this.#send(this.#protocol.writeMessage(JsonHubProtocol.ping()) as string);\n } catch (err) {\n this.#logger.log(LogLevel.Warning, `Ping failed: ${(err as Error).message}`);\n }\n this.#resetPingTimer();\n }, this.#pingInterval);\n }\n\n #resetServerTimeoutTimer(): void {\n clearTimeout(this.#serverTimeoutTimer!);\n this.#serverTimeoutTimer = setTimeout(() => {\n this.#logger.log(LogLevel.Warning, 'Server timeout - closing connection.');\n this.#stopWithError(new AbortError('Server timeout: no message received within the timeout period.'));\n }, this.#serverTimeout);\n }\n\n #clearTimers(): void {\n clearTimeout(this.#pingTimer!);\n clearTimeout(this.#serverTimeoutTimer!);\n clearTimeout(this.#handshakeTimer!);\n this.#pingTimer = null;\n this.#serverTimeoutTimer = null;\n this.#handshakeTimer = null;\n }\n\n // ─── Internal: helpers ────────────────────────────────────────────────────\n\n #send(message: string): Promise<void> {\n this.#resetPingTimer();\n return this.#transport!.send(message);\n }\n\n #assertConnected(method: string): void {\n if (this.#state !== HubConnectionState.Connected) {\n throw new Error(\n `Cannot call \"${method}\" when connection is not Connected (current: ${this.#state}).`\n );\n }\n }\n\n #nextId(): InvocationId {\n return toInvocationId(String(++this.#invocationSeq));\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\n/**\n * Append a single query-string name/value pair to a URL.\n *\n * Uses the WHATWG `URL` API so the operation is always correct regardless of\n * whether the URL already contains a query string, path segments, or both.\n * This avoids the classic bug where naive string concatenation appends a path\n * segment *after* an existing query string, corrupting the URL.\n *\n * e.g. appendParam('https://host/hub?token=x', 'id', 'y')\n * → 'https://host/hub?token=x&id=y' ✓ (not '?token=x&id=y' appended raw)\n */\nfunction appendParam(url: string, name: string, value: string): string {\n const u = new URL(url);\n u.searchParams.append(name, value);\n return u.toString();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * hub-connection-builder.ts\n *\n * Fluent builder for HubConnection - mirrors the official Microsoft client API.\n * Uses `const` type parameters (TS 5.0+) and `NoInfer<T>` (TS 5.4+) where\n * applicable to preserve literal types and prevent unintended widening.\n *\n * Usage\n * ─────\n * const connection = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub', {\n * accessTokenFactory: () => fetchToken(),\n * transport: HttpTransportType.WebSockets,\n * })\n * .configureLogging(LogLevel.Information)\n * .withAutomaticReconnect()\n * .build();\n */\n\nimport { HubConnection } from './hub-connection.js';\nimport type { HubConnectionOptions } from './hub-connection.js';\nimport { resolveLogger } from './logger.js';\nimport { LogLevel, HttpTransportType } from './constants.js';\nimport type { ILogger, IHttpClient, IRetryPolicy, RetryContext, Dispatcher } from './interfaces.js';\nimport { CookieAgent } from '@exhumer/undici-cookie-agent';\nimport { CookieJar } from 'tough-cookie';\n\n/** Default reconnect delay sequence in ms: 0, 2 s, 10 s, 30 s then give up. */\nconst DEFAULT_RETRY_DELAYS = [0, 2_000, 10_000, 30_000] as const satisfies readonly number[];\n\n// ─── withUrl option bag ───────────────────────────────────────────────────────\n\nexport interface UrlOptions {\n /** Async function returning a Bearer token (or null for unauthenticated). */\n readonly accessTokenFactory?: () => Promise<string | null>;\n /**\n * Bitmask of {@link HttpTransportType} values.\n * Defaults to all three transports if omitted.\n */\n readonly transport?: number;\n /** Extra HTTP headers appended to every request (negotiate, upgrade, poll…). */\n readonly headers?: Record<string, string>;\n /**\n * Skip the /negotiate step and connect directly via WebSocket.\n * Only valid when transport is exclusively `HttpTransportType.WebSockets`.\n */\n readonly skipNegotiation?: boolean;\n /** ms before the connection is considered unresponsive (default: 30 000). */\n readonly serverTimeoutInMilliseconds?: number;\n /** ms between keep-alive pings (default: 15 000). */\n readonly keepAliveIntervalInMilliseconds?: number;\n /** ms to wait for the SignalR handshake response (default: 15 000). */\n readonly handshakeTimeoutInMilliseconds?: number;\n}\n\n// ─── HubConnectionBuilder ────────────────────────────────────────────────────\n\nexport class HubConnectionBuilder {\n #url: string | null = null;\n #urlOptions: UrlOptions = {};\n #logger: ILogger | null = null;\n #reconnectPolicy: IRetryPolicy | null = null;\n #dispatcher: Dispatcher | null = null;\n #httpClient: IHttpClient | null = null;\n #cookieJar: CookieJar | null = null;\n\n // ─── withUrl ─────────────────────────────────────────────────────────────\n\n withUrl(url: string, options?: UrlOptions): this {\n if (!url || typeof url !== 'string') {\n throw new TypeError('withUrl requires a non-empty string URL.');\n }\n this.#url = url;\n this.#urlOptions = options ?? {};\n return this;\n }\n\n // ─── withCookies ─────────────────────────────────────────────────────────\n\n /**\n * Enable automatic cookie handling for the entire connection session using\n * a `tough-cookie` `CookieJar` and an `@exhumer/undici-cookie-agent` `CookieAgent`.\n *\n * When enabled, the `CookieAgent` wraps every outgoing request - including\n * the `/negotiate` POST, WebSocket upgrade, SSE long-lived GET, and all\n * long-polling requests - so that:\n *\n * 1. `Set-Cookie` headers in the **negotiate response** (and any subsequent\n * response) are stored in the jar automatically.\n * 2. All subsequent requests from the same session include the matching\n * `Cookie` header, exactly as a browser would.\n *\n * @param jar\n * An existing `CookieJar` to use. Pass your own jar when you need to\n * pre-seed cookies (e.g. an auth session cookie obtained before calling\n * `start()`) or inspect the jar after the session ends.\n * When omitted a new, empty jar is created automatically.\n *\n * @throws if {@link withDispatcher} has already been called. To combine a\n * custom dispatcher (e.g. `ProxyAgent`) with cookie support, compose the\n * `cookie` interceptor onto your dispatcher and pass it to `withDispatcher()`:\n *\n * ```ts\n * import { ProxyAgent } from 'undici';\n * import { cookie, CookieJar } from '@exhumer/signalr-client';\n *\n * const jar = new CookieJar();\n * const agent = new ProxyAgent('http://proxy:8080').compose(cookie({ jar }));\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withDispatcher(agent)\n * .build();\n * ```\n *\n * @example\n * ```ts\n * // Automatic jar - no pre-configuration needed\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withCookies()\n * .build();\n *\n * // Pre-seeded jar - inject a session cookie before connecting\n * import { CookieJar } from '@exhumer/signalr-client';\n * const jar = new CookieJar();\n * await jar.setCookie('session=abc123', 'https://example.com');\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withCookies(jar)\n * .build();\n * ```\n */\n withCookies(jar?: CookieJar): this {\n if (this.#dispatcher !== null) {\n throw new Error(\n 'withCookies() cannot be used after withDispatcher(). ' +\n 'To combine a custom dispatcher with cookie support, compose the ' +\n 'cookie interceptor from @exhumer/undici-cookie-agent onto your ' +\n 'dispatcher and pass it to withDispatcher() instead.',\n );\n }\n this.#cookieJar = jar ?? new CookieJar();\n return this;\n }\n\n // ─── withDispatcher ──────────────────────────────────────────────────────\n\n /**\n * Set the undici `Dispatcher` for the entire connection session.\n *\n * The same dispatcher is used for:\n * • the `/negotiate` HTTP POST\n * • the WebSocket upgrade request\n * • SSE long-lived GET and send POSTs\n * • long-polling GETs, POSTs, and DELETE\n *\n * Accepts any `Dispatcher` subclass: `Agent`, `Pool`, `Client`,\n * `ProxyAgent`, `MockAgent`, etc.\n *\n * To combine a custom dispatcher with automatic cookie handling, use\n * `createCookieAgentClass()` to build a cookie-aware variant of your\n * dispatcher and pass that here. Do **not** chain both\n * `withDispatcher()` and `withCookies()` - they are mutually exclusive\n * because `withCookies()` creates its own dispatcher internally.\n *\n * @example\n * ```ts\n * import { ProxyAgent } from 'undici';\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withDispatcher(new ProxyAgent('http://proxy:8080'))\n * .build();\n * ```\n */\n withDispatcher(dispatcher: Dispatcher): this {\n if (this.#cookieJar !== null) {\n throw new Error(\n 'withDispatcher() cannot be used after withCookies(). ' +\n 'To combine a custom dispatcher with cookie support, compose the ' +\n 'cookie interceptor from @exhumer/undici-cookie-agent onto your ' +\n 'dispatcher and pass it to withDispatcher() instead.',\n );\n }\n this.#dispatcher = dispatcher;\n return this;\n }\n\n /**\n * Provide a custom HTTP client implementation.\n *\n * By default `HubConnection` uses `DispatchHttpClient` (undici `dispatch`).\n * Use this to substitute any of the other undici-backed clients, or\n * to inject a mock for testing.\n *\n * @example\n * ```ts\n * import { FetchHttpClient } from '@signalr/client';\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withHttpClient(new FetchHttpClient())\n * .build();\n * ```\n */\n withHttpClient(httpClient: IHttpClient): this {\n this.#httpClient = httpClient;\n return this;\n }\n\n // ─── configureLogging ────────────────────────────────────────────────────\n\n /**\n * Set the minimum log level or provide a custom logger.\n *\n * @param logLevelOrLogger\n * - `LogLevel` number → uses the built-in ConsoleLogger\n * - `ILogger` object → used as-is\n */\n configureLogging(logLevelOrLogger: LogLevel | ILogger): this {\n this.#logger = resolveLogger(logLevelOrLogger);\n return this;\n }\n\n // ─── withAutomaticReconnect ───────────────────────────────────────────────\n\n /**\n * Enable automatic reconnection on unexpected disconnections.\n *\n * @overload withAutomaticReconnect()\n * Uses the built-in delay sequence: 0 ms, 2 s, 10 s, 30 s.\n *\n * @overload withAutomaticReconnect(retryDelays: readonly number[])\n * Each element is the wait (ms) before the corresponding retry.\n * Reconnection stops after all delays are exhausted.\n * Uses `NoInfer<number>` so literals are not widened unexpectedly.\n *\n * @overload withAutomaticReconnect(policy: IRetryPolicy)\n * Custom policy. Return `null` from\n * `nextRetryDelayInMilliseconds` to stop retrying.\n */\n withAutomaticReconnect(): this;\n withAutomaticReconnect(retryDelays: readonly NoInfer<number>[]): this;\n withAutomaticReconnect(policy: IRetryPolicy): this;\n withAutomaticReconnect(\n arg?: readonly number[] | IRetryPolicy,\n ): this {\n if (arg === undefined) {\n this.#reconnectPolicy = new DefaultReconnectPolicy([...DEFAULT_RETRY_DELAYS]);\n } else if (Array.isArray(arg)) {\n this.#reconnectPolicy = new DefaultReconnectPolicy(arg);\n } else if (\n typeof arg === 'object' &&\n typeof (arg as IRetryPolicy).nextRetryDelayInMilliseconds === 'function'\n ) {\n this.#reconnectPolicy = arg as IRetryPolicy;\n } else {\n throw new TypeError(\n 'withAutomaticReconnect expects no args, a number[], or an IRetryPolicy.'\n );\n }\n return this;\n }\n\n // ─── build ───────────────────────────────────────────────────────────────\n\n build(): HubConnection {\n if (!this.#url) {\n throw new Error('withUrl() must be called before build().');\n }\n\n // If withCookies() was called, create a CookieAgent as the dispatcher so\n // that Set-Cookie headers from /negotiate are stored and Cookie headers\n // are forwarded to every subsequent request (WebSocket upgrade, SSE GET,\n // long-polling GET/POST/DELETE) - all of which share this dispatcher.\n const effectiveDispatcher: Dispatcher | null =\n this.#cookieJar !== null\n ? new CookieAgent({ cookies: { jar: this.#cookieJar } })\n : this.#dispatcher;\n\n // exactOptionalPropertyTypes: spread only defined values so we never\n // explicitly assign `undefined` to an optional property.\n const options: HubConnectionOptions = {\n ...(this.#logger != null && { logger: this.#logger }),\n ...(this.#urlOptions.accessTokenFactory != null && { accessTokenFactory: this.#urlOptions.accessTokenFactory }),\n ...(this.#urlOptions.transport != null && { transport: this.#urlOptions.transport }),\n ...(this.#urlOptions.headers != null && { headers: this.#urlOptions.headers }),\n ...(this.#urlOptions.skipNegotiation != null && { skipNegotiation: this.#urlOptions.skipNegotiation }),\n ...(this.#urlOptions.serverTimeoutInMilliseconds != null && { serverTimeoutInMilliseconds: this.#urlOptions.serverTimeoutInMilliseconds }),\n ...(this.#urlOptions.keepAliveIntervalInMilliseconds != null && { keepAliveIntervalInMilliseconds: this.#urlOptions.keepAliveIntervalInMilliseconds }),\n ...(this.#urlOptions.handshakeTimeoutInMilliseconds != null && { handshakeTimeoutInMilliseconds: this.#urlOptions.handshakeTimeoutInMilliseconds }),\n ...(this.#reconnectPolicy != null && { reconnectPolicy: this.#reconnectPolicy }),\n ...(effectiveDispatcher != null && { dispatcher: effectiveDispatcher }),\n ...(this.#httpClient != null && { httpClient: this.#httpClient }),\n };\n\n return new HubConnection(this.#url, options);\n }\n}\n\n// ─── Default reconnect policy ─────────────────────────────────────────────────\n\nexport class DefaultReconnectPolicy implements IRetryPolicy {\n readonly #retryDelays: readonly number[];\n\n constructor(retryDelays: readonly number[] = [...DEFAULT_RETRY_DELAYS]) {\n this.#retryDelays = retryDelays;\n }\n\n nextRetryDelayInMilliseconds(context: RetryContext): number | null {\n const delay = this.#retryDelays[context.previousRetryCount];\n return delay ?? null;\n }\n}\n","/**\n * msgpack-hub-protocol.ts\n *\n * Implements the SignalR Hub Protocol over MessagePack (version 1).\n *\n * Wire format\n * ───────────\n * • Handshake: JSON text terminated by ASCII 0x1e - identical to the JSON\n * protocol, only the \"protocol\" field changes to \"messagepack\".\n * • All subsequent messages: binary MessagePack, each frame prefixed by a\n * base-128 VarInt carrying the byte-length of the following MessagePack\n * payload. A single transport payload may contain multiple such frames.\n *\n * MessagePack array layout (per message type)\n * ────────────────────────────────────────────\n * Invocation [1, headers, invocationId|null, target, args, streamIds]\n * StreamItem [2, headers, invocationId, item]\n * Completion [3, headers, invocationId, resultKind, value?]\n * resultKind: 1 = error string, 2 = void, 3 = non-void result value\n * StreamInvocation [4, headers, invocationId, target, args, streamIds]\n * CancelInvocation [5, headers, invocationId]\n * Ping [6]\n * Close [7, error|null, allowReconnect]\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport { encode, decode } from '@msgpack/msgpack';\nimport { MessageType, TransferFormat, RECORD_SEPARATOR } from '../constants.js';\nimport type { IHubProtocol, ILogger } from '../interfaces.js';\nimport {\n type HubMessage,\n type InvocationMessage,\n type StreamInvocationMessage,\n type CancelInvocationMessage,\n type CompletionMessage,\n type StreamItemMessage,\n type PingMessage,\n type CloseMessage,\n type InvocationId,\n toInvocationId,\n} from '../messages.js';\n\n// ─── Handshake constants ──────────────────────────────────────────────────────\n\n/**\n * The JSON-formatted handshake request the client sends once the transport\n * is open. The server always responds with JSON ({} on success), regardless\n * of the chosen hub protocol.\n */\nexport const HANDSHAKE_REQUEST =\n JSON.stringify({ protocol: 'messagepack', version: 1 }) + RECORD_SEPARATOR;\n\n// The handshake *response* is always JSON - re-export the same parser that\n// JsonHubProtocol uses.\nexport {\n parseHandshakeResponse,\n type HandshakeResponse,\n type HandshakeParseResult,\n} from './json-hub-protocol.js';\n\n// ─── Completion result-kind constants ─────────────────────────────────────────\n\nconst ResultKind = Object.freeze({\n Error: 1,\n Void: 2,\n NonVoid: 3,\n} as const);\n\ntype ResultKindValue = (typeof ResultKind)[keyof typeof ResultKind];\n\n// ─── VarInt framing (base-128 variable-length integer) ───────────────────────\n\n/** Write `n` as a base-128 VarInt (little-endian groups of 7 bits). */\nfunction writeVarInt(n: number): Uint8Array {\n const bytes: number[] = [];\n do {\n let b = n & 0x7f;\n n >>>= 7;\n if (n > 0) b |= 0x80;\n bytes.push(b);\n } while (n > 0);\n return new Uint8Array(bytes);\n}\n\n/** Read a VarInt from `data` starting at `offset`. Returns value + bytes consumed. */\nfunction readVarInt(data: Uint8Array, offset: number): { value: number; bytesRead: number } {\n let value = 0;\n let shift = 0;\n let bytesRead = 0;\n let hasMore = true;\n while (hasMore) {\n if (offset + bytesRead >= data.length) {\n throw new Error('MessagePack: unexpected end of data reading VarInt frame length.');\n }\n const byte = data[offset + bytesRead]!;\n hasMore = (byte & 0x80) !== 0;\n value |= (byte & 0x7f) << shift;\n shift += 7;\n bytesRead++;\n }\n return { value, bytesRead };\n}\n\n// ─── Frame helper: encode a MessagePack array + prepend VarInt length ─────────\n\nfunction pack(arr: unknown[]): ArrayBuffer {\n const payload = encode(arr);\n const lenPrefix = writeVarInt(payload.length);\n const result = new Uint8Array(lenPrefix.length + payload.length);\n result.set(lenPrefix, 0);\n result.set(payload, lenPrefix.length);\n // Return a standalone ArrayBuffer (not a shared typed-array view).\n return result.buffer.slice(0, result.byteLength);\n}\n\n// ─── Protocol class ───────────────────────────────────────────────────────────\n\nexport class MsgpackHubProtocol implements IHubProtocol {\n readonly name = 'messagepack' as const;\n readonly version = 1 as const;\n readonly transferFormat = TransferFormat.Binary;\n\n // ─── IHubProtocol: parseMessages ─────────────────────────────────────\n\n parseMessages(input: string | ArrayBuffer, logger: ILogger): HubMessage[] {\n // The binary transport always delivers ArrayBuffer; accept string as a\n // convenience for testing (treat as UTF-8 encoded bytes).\n const raw: ArrayBuffer =\n typeof input === 'string'\n ? new TextEncoder().encode(input).buffer\n : input;\n\n const data = new Uint8Array(raw);\n if (data.length === 0) return [];\n\n const messages: HubMessage[] = [];\n let offset = 0;\n\n while (offset < data.length) {\n const { value: msgLen, bytesRead } = readVarInt(data, offset);\n offset += bytesRead;\n\n if (offset + msgLen > data.length) {\n throw new Error(\n `MessagePack hub message: declared length ${msgLen} B exceeds ` +\n `remaining data (${data.length - offset} B).`,\n );\n }\n\n const frame = data.subarray(offset, offset + msgLen);\n offset += msgLen;\n\n const rawArr = decode(frame);\n if (!Array.isArray(rawArr) || rawArr.length === 0) {\n throw new Error(\n 'Invalid MessagePack hub message: top-level value must be a non-empty array.',\n );\n }\n\n const msg = this.#coerce(rawArr, logger);\n if (msg !== null) messages.push(msg);\n }\n\n return messages;\n }\n\n // ─── IHubProtocol: writeMessage ───────────────────────────────────────\n\n writeMessage(message: HubMessage): ArrayBuffer {\n switch (message.type) {\n\n case MessageType.Invocation:\n return pack([\n MessageType.Invocation,\n message.headers ?? {},\n message.invocationId ?? null,\n message.target,\n message.arguments,\n message.streamIds ?? [],\n ]);\n\n case MessageType.StreamItem:\n return pack([\n MessageType.StreamItem,\n message.headers ?? {},\n message.invocationId,\n message.item,\n ]);\n\n case MessageType.Completion: {\n const hasError = message.error != null;\n const hasResult = message.result != null;\n if (hasError) {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.Error,\n message.error,\n ]);\n } else if (hasResult) {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.NonVoid,\n message.result,\n ]);\n } else {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.Void,\n ]);\n }\n }\n\n case MessageType.StreamInvocation:\n return pack([\n MessageType.StreamInvocation,\n message.headers ?? {},\n message.invocationId,\n message.target,\n message.arguments,\n message.streamIds ?? [],\n ]);\n\n case MessageType.CancelInvocation:\n return pack([\n MessageType.CancelInvocation,\n message.headers ?? {},\n message.invocationId,\n ]);\n\n case MessageType.Ping:\n return pack([MessageType.Ping]);\n\n case MessageType.Close: {\n const arr: unknown[] = [MessageType.Close, message.error ?? null];\n if (message.allowReconnect !== undefined) arr.push(message.allowReconnect);\n return pack(arr);\n }\n }\n }\n\n // ─── Coercion / narrowing ─────────────────────────────────────────────\n\n /**\n * Validate and narrow a raw decoded array into a typed `HubMessage`.\n * Returns `null` for unknown types - they are logged as warnings.\n */\n #coerce(arr: unknown[], logger: ILogger): HubMessage | null {\n const type = arr[0];\n if (typeof type !== 'number') {\n throw new Error(\n `Invalid MessagePack hub message: first element (type) must be a number, ` +\n `got ${JSON.stringify(type)}.`,\n );\n }\n\n switch (type) {\n case MessageType.Invocation: return this.#coerceInvocation(arr);\n case MessageType.StreamItem: return this.#coerceStreamItem(arr);\n case MessageType.Completion: return this.#coerceCompletion(arr);\n case MessageType.StreamInvocation: return this.#coerceStreamInvocation(arr);\n case MessageType.CancelInvocation: return this.#coerceCancelInvocation(arr);\n case MessageType.Ping: return this.#coercePing();\n case MessageType.Close: return this.#coerceClose(arr);\n default:\n logger.log(3 /* Warning */, `Ignoring MessagePack message with unknown type ${String(type)}.`);\n return null;\n }\n }\n\n // ── [1, headers, invocationId|null, target, arguments, streamIds] ─────\n\n #coerceInvocation(arr: unknown[]): InvocationMessage {\n const target = arr[3];\n const args = arr[4];\n if (typeof target !== 'string') {\n throw new Error(\"Invalid Invocation message: index 3 ('target') must be a string.\");\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Invalid Invocation message: index 4 ('arguments') must be an array.\");\n }\n const rawId = arr[2];\n const rawSids = arr[5];\n const rawHdrs = arr[1];\n return {\n type: MessageType.Invocation,\n target,\n arguments: args as unknown[],\n ...(rawId != null && rawId !== '' && rawId !== null && { invocationId: toInvocationId(String(rawId)) }),\n ...(Array.isArray(rawSids) && rawSids.length > 0 && { streamIds: rawSids as string[] }),\n ...(isNonEmptyObject(rawHdrs) && { headers: rawHdrs as Record<string, string> }),\n };\n }\n\n // ── [2, headers, invocationId, item] ─────────────────────────────────\n\n #coerceStreamItem(arr: unknown[]): StreamItemMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid StreamItem message: index 2 ('invocationId') is required.\");\n }\n return {\n type: MessageType.StreamItem,\n invocationId: toInvocationId(String(rawId)),\n item: arr[3],\n ...(isNonEmptyObject(arr[1]) && { headers: arr[1] as Record<string, string> }),\n };\n }\n\n // ── [3, headers, invocationId, resultKind, value?] ───────────────────\n\n #coerceCompletion(arr: unknown[]): CompletionMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid Completion message: index 2 ('invocationId') is required.\");\n }\n const invocationId = toInvocationId(String(rawId));\n const resultKind = arr[3] as ResultKindValue;\n const hdrs = isNonEmptyObject(arr[1]) ? { headers: arr[1] as Record<string, string> } : {};\n\n switch (resultKind) {\n case ResultKind.Error:\n return { type: MessageType.Completion, invocationId, error: String(arr[4] ?? ''), ...hdrs };\n case ResultKind.Void:\n return { type: MessageType.Completion, invocationId, ...hdrs };\n case ResultKind.NonVoid:\n return { type: MessageType.Completion, invocationId, result: arr[4], ...hdrs };\n default:\n throw new Error(`Invalid Completion message: unknown resultKind ${String(resultKind)}.`);\n }\n }\n\n // ── [4, headers, invocationId, target, arguments, streamIds] ─────────\n\n #coerceStreamInvocation(arr: unknown[]): StreamInvocationMessage {\n const rawId = arr[2];\n const target = arr[3];\n const args = arr[4];\n if (rawId == null) {\n throw new Error(\"Invalid StreamInvocation message: index 2 ('invocationId') is required.\");\n }\n if (typeof target !== 'string') {\n throw new Error(\"Invalid StreamInvocation message: index 3 ('target') must be a string.\");\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Invalid StreamInvocation message: index 4 ('arguments') must be an array.\");\n }\n const rawSids = arr[5];\n return {\n type: MessageType.StreamInvocation,\n invocationId: toInvocationId(String(rawId)),\n target,\n arguments: args as unknown[],\n ...(Array.isArray(rawSids) && rawSids.length > 0 && { streamIds: rawSids as string[] }),\n ...(isNonEmptyObject(arr[1]) && { headers: arr[1] as Record<string, string> }),\n };\n }\n\n // ── [5, headers, invocationId] ───────────────────────────────────────\n\n #coerceCancelInvocation(arr: unknown[]): CancelInvocationMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid CancelInvocation message: index 2 ('invocationId') is required.\");\n }\n return {\n type: MessageType.CancelInvocation,\n invocationId: toInvocationId(String(rawId)),\n ...(isNonEmptyObject(arr[1]) && { headers: arr[1] as Record<string, string> }),\n };\n }\n\n // ── [6] ──────────────────────────────────────────────────────────────\n\n #coercePing(): PingMessage { return { type: MessageType.Ping }; }\n\n // ── [7, error|null, allowReconnect] ──────────────────────────────────\n\n #coerceClose(arr: unknown[]): CloseMessage {\n return {\n type: MessageType.Close,\n ...(arr[1] != null && { error: String(arr[1]) }),\n ...(arr[2] != null && { allowReconnect: Boolean(arr[2]) }),\n };\n }\n\n // ─── Static message factories (mirrors JsonHubProtocol API) ──────────\n\n static invocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n /** Fire-and-forget (no `invocationId`). */\n static send(\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static streamInvocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): StreamInvocationMessage {\n return {\n type: MessageType.StreamInvocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static cancelInvocation(invocationId: InvocationId): CancelInvocationMessage {\n return { type: MessageType.CancelInvocation, invocationId };\n }\n\n static streamItem(invocationId: InvocationId, item: unknown): StreamItemMessage {\n return { type: MessageType.StreamItem, invocationId, item };\n }\n\n static completion(\n invocationId: InvocationId,\n result: unknown,\n error: string | null,\n ): CompletionMessage {\n return {\n type: MessageType.Completion,\n invocationId,\n ...(error != null && { error }),\n ...(result != null && { result }),\n };\n }\n\n static ping(): PingMessage { return { type: MessageType.Ping }; }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isNonEmptyObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v) &&\n Object.keys(v as object).length > 0;\n}\n","/**\n * ws-client.ts\n *\n * From-scratch WebSocket client (RFC 6455) built on Node's built-in `net`\n * and `tls` modules. Zero external runtime dependencies.\n *\n * Typed EventEmitter via interface declaration merging.\n *\n * Emitted events\n * 'open' - handshake complete, ready to send/receive\n * 'message' (string) - UTF-8 text frame received\n * 'binary' (Buffer) - binary frame received\n * 'ping' (Buffer) - ping frame received (pong sent automatically)\n * 'pong' (Buffer) - pong frame received\n * 'close' - socket fully closed\n * 'error' (Error) - socket-level error\n */\n\nimport * as net from 'node:net';\nimport * as tls from 'node:tls';\nimport * as crypto from 'node:crypto';\nimport { EventEmitter } from 'node:events';\n\n// ─── RFC 6455 opcodes ─────────────────────────────────────────────────────────\nconst enum Opcode {\n Continuation = 0x0,\n Text = 0x1,\n Binary = 0x2,\n Close = 0x8,\n Ping = 0x9,\n Pong = 0xa,\n}\n\n// ─── Connection states ────────────────────────────────────────────────────────\nexport const enum WebSocketReadyState {\n Connecting = 0,\n Open = 1,\n Closing = 2,\n Closed = 3,\n}\n\nconst WS_MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';\n\n// ─── Typed-EventEmitter overloads (declaration merging) ───────────────────────\n\nexport interface WebSocketClient {\n on(event: 'open', listener: () => void): this;\n on(event: 'message', listener: (data: string) => void): this;\n on(event: 'binary', listener: (data: Buffer) => void): this;\n on(event: 'ping', listener: (data: Buffer) => void): this;\n on(event: 'pong', listener: (data: Buffer) => void): this;\n on(event: 'close', listener: () => void): this;\n on(event: 'error', listener: (err: Error) => void): this;\n\n once(event: 'open', listener: () => void): this;\n once(event: 'message', listener: (data: string) => void): this;\n once(event: 'close', listener: () => void): this;\n once(event: 'error', listener: (err: Error) => void): this;\n\n emit(event: 'open'): boolean;\n emit(event: 'message', data: string): boolean;\n emit(event: 'binary', data: Buffer): boolean;\n emit(event: 'ping', data: Buffer): boolean;\n emit(event: 'pong', data: Buffer): boolean;\n emit(event: 'close'): boolean;\n emit(event: 'error', err: Error): boolean;\n\n removeAllListeners(event?: string): this;\n}\n\n// ─── Parsed frame ─────────────────────────────────────────────────────────────\ninterface ParsedFrame {\n fin: boolean;\n opcode: number;\n payload: Buffer;\n}\n\ninterface ParseResult {\n frame: ParsedFrame;\n consumed: number;\n}\n\n// ─── Implementation ───────────────────────────────────────────────────────────\n\nexport class WebSocketClient extends EventEmitter {\n #socket: net.Socket | null = null;\n #state: WebSocketReadyState = WebSocketReadyState.Closed;\n #frameBuf: Buffer = Buffer.alloc(0);\n #fragments: Buffer[] = [];\n #fragmentOpcode: number | null = null;\n #handshakeBuf: Buffer = Buffer.alloc(0);\n #handshakeResolve: (() => void) | null = null;\n #handshakeReject: ((e: Error) => void) | null = null;\n\n get readyState(): WebSocketReadyState { return this.#state; }\n\n // ─── Public API ─────────────────────────────────────────────────────────\n\n /**\n * Open a WebSocket connection.\n * @param url ws:// or wss:// URL\n * @param headers Extra HTTP headers for the upgrade request\n */\n connect(url: string, headers: Record<string, string> = {}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.#state !== WebSocketReadyState.Closed) {\n reject(new Error('WebSocket is already open or connecting.'));\n return;\n }\n this.#state = WebSocketReadyState.Connecting;\n this.#handshakeResolve = resolve;\n this.#handshakeReject = reject;\n\n const parsed = new URL(url);\n const isSecure = parsed.protocol === 'wss:';\n const host = parsed.hostname;\n const port = Number(parsed.port) || (isSecure ? 443 : 80);\n const resource = (parsed.pathname || '/') + (parsed.search || '');\n const portSuffix = parsed.port ? `:${parsed.port}` : '';\n\n const nonce = crypto.randomBytes(16).toString('base64');\n const expected = computeAccept(nonce);\n\n const upgradeLines: string[] = [\n `GET ${resource} HTTP/1.1`,\n `Host: ${host}${portSuffix}`,\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Key: ${nonce}`,\n 'Sec-WebSocket-Version: 13',\n ...Object.entries(headers).map(([k, v]) => `${k}: ${v}`),\n '',\n '',\n ];\n const request = upgradeLines.join('\\r\\n');\n\n const onSocketData = (chunk: Buffer): void => {\n this.#onHandshakeData(chunk, expected);\n };\n\n const socketOpts = { host, port };\n if (isSecure) {\n this.#socket = tls.connect({ ...socketOpts, servername: host }, () => {\n this.#socket!.write(request);\n });\n } else {\n this.#socket = net.connect(socketOpts, () => {\n this.#socket!.write(request);\n });\n }\n\n this.#socket.on('data', onSocketData);\n this.#socket.on('error', (err: Error) => {\n if (this.#state === WebSocketReadyState.Connecting) {\n this.#state = WebSocketReadyState.Closed;\n this.#handshakeReject!(err);\n } else if (this.#state !== WebSocketReadyState.Closing) {\n // Errors during the Closing state (e.g. ECONNRESET after ws.close())\n // are expected and should not surface to callers.\n this.emit('error', err);\n }\n });\n this.#socket.on('close', () => this.#onSocketClose());\n this.#socket.on('end', () => this.#socket?.destroy());\n });\n }\n\n /**\n * Send a text or binary message.\n * @throws if the socket is not open.\n */\n send(data: string | Buffer | Uint8Array): void {\n if (this.#state !== WebSocketReadyState.Open) {\n throw new Error('WebSocket is not open.');\n }\n if (typeof data === 'string') {\n this.#writeFrame(Opcode.Text, Buffer.from(data, 'utf8'));\n } else {\n this.#writeFrame(Opcode.Binary, Buffer.isBuffer(data) ? data : Buffer.from(data));\n }\n }\n\n /**\n * Initiate a clean close handshake.\n * @param code WebSocket close code (default 1000 = Normal Closure)\n * @param reason UTF-8 reason string (max 123 bytes)\n */\n close(code = 1000, reason = ''): void {\n if (this.#state !== WebSocketReadyState.Open) return;\n this.#state = WebSocketReadyState.Closing;\n const reasonBuf = Buffer.from(reason, 'utf8');\n const payload = Buffer.allocUnsafe(2 + reasonBuf.length);\n payload.writeUInt16BE(code, 0);\n reasonBuf.copy(payload, 2);\n this.#writeFrame(Opcode.Close, payload);\n }\n\n // ─── Handshake ───────────────────────────────────────────────────────────\n\n #onHandshakeData(chunk: Buffer, expectedAccept: string): void {\n this.#handshakeBuf = Buffer.concat([this.#handshakeBuf, chunk]);\n\n const idx = indexOfCRLFCRLF(this.#handshakeBuf);\n if (idx === -1) return; // Wait for the full header block\n\n const headerStr = this.#handshakeBuf.subarray(0, idx).toString('ascii');\n const remainder = this.#handshakeBuf.subarray(idx + 4);\n\n const lines = headerStr.split('\\r\\n');\n const statusLine = lines[0] ?? '';\n\n if (!statusLine.includes('101')) {\n this.#failHandshake(\n new Error(`WebSocket upgrade failed - server replied: ${statusLine}`)\n );\n return;\n }\n\n let accept = '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i]!;\n const colon = line.indexOf(':');\n if (colon === -1) continue;\n if (line.slice(0, colon).trim().toLowerCase() === 'sec-websocket-accept') {\n accept = line.slice(colon + 1).trim();\n break;\n }\n }\n\n if (accept !== expectedAccept) {\n this.#failHandshake(\n new Error(`Invalid Sec-WebSocket-Accept (got \"${accept}\", expected \"${expectedAccept}\")`)\n );\n return;\n }\n\n // Success - switch to frame-processing mode\n this.#state = WebSocketReadyState.Open;\n this.#handshakeBuf = Buffer.alloc(0);\n this.#socket!.removeAllListeners('data');\n this.#socket!.on('data', (c: Buffer) => this.#onFrameData(c));\n\n const r = this.#handshakeResolve!;\n this.#handshakeResolve = null;\n this.#handshakeReject = null;\n r();\n this.emit('open');\n\n if (remainder.length > 0) this.#onFrameData(remainder);\n }\n\n #failHandshake(err: Error): void {\n this.#state = WebSocketReadyState.Closed;\n this.#socket?.destroy();\n const r = this.#handshakeReject!;\n this.#handshakeResolve = null;\n this.#handshakeReject = null;\n r(err);\n }\n\n // ─── Frame parsing ───────────────────────────────────────────────────────\n\n #onFrameData(chunk: Buffer): void {\n this.#frameBuf = Buffer.concat([this.#frameBuf, chunk]);\n this.#drainFrames();\n }\n\n #drainFrames(): void {\n for (;;) {\n const result = tryParseFrame(this.#frameBuf);\n if (!result) break;\n this.#frameBuf = this.#frameBuf.subarray(result.consumed);\n this.#dispatchFrame(result.frame);\n }\n }\n\n #dispatchFrame({ fin, opcode, payload }: ParsedFrame): void {\n switch (opcode) {\n case Opcode.Text:\n case Opcode.Binary:\n if (!fin) {\n this.#fragmentOpcode = opcode;\n this.#fragments = [payload];\n } else {\n this.#emitData(opcode, payload);\n }\n break;\n\n case Opcode.Continuation:\n this.#fragments.push(payload);\n if (fin) {\n const full = Buffer.concat(this.#fragments);\n const op = this.#fragmentOpcode!;\n this.#fragments = [];\n this.#fragmentOpcode = null;\n this.#emitData(op, full);\n }\n break;\n\n case Opcode.Ping:\n this.#writeFrame(Opcode.Pong, payload);\n this.emit('ping', payload);\n break;\n\n case Opcode.Pong:\n this.emit('pong', payload);\n break;\n\n case Opcode.Close:\n if (this.#state === WebSocketReadyState.Open) {\n this.#writeFrame(Opcode.Close, payload);\n }\n this.#state = WebSocketReadyState.Closed;\n this.#socket?.destroy();\n this.emit('close');\n break;\n\n default:\n // Unknown opcode - ignore per RFC 6455 §5.2\n break;\n }\n }\n\n #emitData(opcode: number, payload: Buffer): void {\n if (opcode === Opcode.Text) {\n this.emit('message', payload.toString('utf8'));\n } else {\n this.emit('binary', payload);\n }\n }\n\n // ─── Frame writing ───────────────────────────────────────────────────────\n\n /**\n * Encode and send one WebSocket frame.\n * All client→server frames MUST be masked (RFC 6455 §5.3).\n */\n #writeFrame(opcode: Opcode, payload: Buffer = Buffer.alloc(0), fin = true): void {\n if (!this.#socket || this.#socket.destroyed) return;\n\n const len = payload.length;\n\n // ── Header ──────────────────────────────────────────────────────────\n let header: Buffer;\n if (len < 126) {\n header = Buffer.allocUnsafe(2);\n header[1] = 0x80 | len; // MASK bit + length\n } else if (len < 65_536) {\n header = Buffer.allocUnsafe(4);\n header[1] = 0x80 | 126;\n header.writeUInt16BE(len, 2);\n } else {\n header = Buffer.allocUnsafe(10);\n header[1] = 0x80 | 127;\n header.writeUInt32BE(0, 2);\n header.writeUInt32BE(len, 6);\n }\n header[0] = (fin ? 0x80 : 0x00) | opcode;\n\n // ── Masking ─────────────────────────────────────────────────────────\n const maskKey = crypto.randomBytes(4);\n const maskedPayload = Buffer.allocUnsafe(len);\n for (let i = 0; i < len; i++) {\n maskedPayload[i] = payload[i]! ^ maskKey[i % 4]!;\n }\n\n this.#socket.write(Buffer.concat([header, maskKey, maskedPayload]));\n }\n\n // ─── Socket events ───────────────────────────────────────────────────────\n\n #onSocketClose(): void {\n if (this.#state !== WebSocketReadyState.Closed) {\n this.#state = WebSocketReadyState.Closed;\n this.emit('close');\n }\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\nfunction computeAccept(key: string): string {\n return crypto.createHash('sha1').update(key + WS_MAGIC).digest('base64');\n}\n\nfunction indexOfCRLFCRLF(buf: Buffer): number {\n for (let i = 0; i <= buf.length - 4; i++) {\n if (buf[i] === 0x0d && buf[i + 1] === 0x0a &&\n buf[i + 2] === 0x0d && buf[i + 3] === 0x0a) {\n return i;\n }\n }\n return -1;\n}\n\nfunction tryParseFrame(buf: Buffer): ParseResult | null {\n if (buf.length < 2) return null;\n\n const b0 = buf[0]!;\n const b1 = buf[1]!;\n const fin = (b0 & 0x80) !== 0;\n const opcode = b0 & 0x0f;\n const masked = (b1 & 0x80) !== 0;\n let payLen = b1 & 0x7f;\n let offset = 2;\n\n if (payLen === 126) {\n if (buf.length < offset + 2) return null;\n payLen = buf.readUInt16BE(offset);\n offset += 2;\n } else if (payLen === 127) {\n if (buf.length < offset + 8) return null;\n const hi = buf.readUInt32BE(offset);\n if (hi !== 0) throw new Error('Received a frame with payload > 4 GB - not supported.');\n payLen = buf.readUInt32BE(offset + 4);\n offset += 8;\n }\n\n let maskBytes: Buffer | null = null;\n if (masked) {\n if (buf.length < offset + 4) return null;\n maskBytes = buf.subarray(offset, offset + 4);\n offset += 4;\n }\n\n if (buf.length < offset + payLen) return null;\n\n let payload = buf.subarray(offset, offset + payLen);\n if (masked && maskBytes !== null) {\n payload = Buffer.from(payload);\n for (let i = 0; i < payload.length; i++) {\n // noUncheckedIndexedAccess: both sides are within-bounds by construction\n payload[i] = (payload[i] as number) ^ (maskBytes[i % 4] as number);\n }\n }\n\n return { frame: { fin, opcode, payload }, consumed: offset + payLen };\n}\n"],"mappings":"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","names":["HANDSHAKE_REQUEST","WebSocketReadyState","undiciRequest","undiciFetch","undiciStream","undiciPipeline","headers","import_undici","HANDSHAKE_REQUEST","WebSocketReadyState","import_tough_cookie","import_undici_cookie_agent"]}
1
+ {"version":3,"file":"index.cjs","names":["getGlobalDispatcher","undiciRequest","undiciFetch","Readable","undiciStream","PassThrough","undiciPipeline","parseInvocationId","parseStreamIds","parseHeaders","WebSocketReadyState","WebSocket","CookieJar","CookieAgent","HANDSHAKE_REQUEST","Encoder","decode","EventEmitter","crypto","tls","net"],"sources":["../src/http-client.ts","../src/constants.ts","../src/messages.ts","../src/protocols/json-hub-protocol.ts","../src/transports/websocket-transport.ts","../src/transports/sse-transport.ts","../src/transports/long-polling-transport.ts","../src/logger.ts","../src/errors.ts","../src/hub-connection.ts","../src/hub-connection-builder.ts","../src/protocols/msgpack-hub-protocol.ts","../src/ws-client.ts"],"sourcesContent":["/**\n * http-client.ts\n *\n * Five HTTP client implementations backed by undici, each wrapping a different\n * undici primitive. All five satisfy the `IHttpClient` contract so any one\n * can be used wherever an HTTP client is required (negotiate, SSE, polling…).\n *\n * ┌────────────────────┬───────────────────────────────────────────────────┐\n * │ Class │ undici primitive │\n * ├────────────────────┼───────────────────────────────────────────────────┤\n * │ RequestHttpClient │ undici.request() │\n * │ FetchHttpClient │ undici.fetch() (WHATWG-compatible) │\n * │ StreamHttpClient │ undici.stream() (factory-based streaming) │\n * │ PipelineHttpClient │ undici.pipeline() (Duplex pipe chain) │\n * │ DispatchHttpClient │ Dispatcher#dispatch (low-level handler interface) ← DEFAULT │\n * └────────────────────┴───────────────────────────────────────────────────┘\n *\n * Dispatcher (session-level):\n * Every client accepts an optional `dispatcher` option. Pass an undici\n * `Agent`, `Pool`, `Client`, `ProxyAgent`, etc. to customise connection\n * pooling, proxy routing, TLS, or any other transport-level behaviour for\n * the entire client session. When omitted, undici's process-global\n * default agent is used (`getGlobalDispatcher()`).\n *\n * HttpClient:\n * An alias for `DispatchHttpClient` so existing code that imported\n * `HttpClient` continues to work without changes.\n */\n\nimport { PassThrough, Readable } from 'node:stream';\nimport {\n request as undiciRequest,\n stream as undiciStream,\n pipeline as undiciPipeline,\n fetch as undiciFetch,\n getGlobalDispatcher,\n type Dispatcher,\n} from 'undici';\n\nimport type { HttpResponse, StreamResult, IHttpClient } from './interfaces.js';\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';\n\n/**\n * Per-request options accepted by every client method.\n * These mirror the previous `node:http`-based API surface exactly so callers\n * do not need to be changed when switching client implementations.\n */\nexport interface RequestOptions {\n /** Per-request headers merged on top of the instance-level defaults. */\n readonly headers?: Record<string, string>;\n /**\n * Request body.\n * Plain objects are serialised to JSON automatically.\n * Strings are sent as-is (set Content-Type explicitly if needed).\n */\n readonly body?: string | Uint8Array | Record<string, unknown> | null;\n /** Override the session-level timeout for this single request (ms). */\n readonly timeout?: number;\n}\n\n/**\n * Session-level options shared by all client constructors.\n */\nexport interface HttpClientOptions {\n /** Headers sent with every request (merged before per-request headers). */\n readonly headers?: Record<string, string>;\n /** Default timeout in milliseconds applied to every request (default: 30 000). */\n readonly timeout?: number;\n /**\n * undici Dispatcher to use for the entire session.\n *\n * You can pass any `Dispatcher` subclass:\n * - `new undici.Agent(opts)` - connection-pool tuning\n * - `new undici.Pool(origin, opts)` - per-origin pool\n * - `new undici.Client(origin, opts)` - single connection\n * - `new undici.ProxyAgent(proxyUrl)` - HTTP proxy\n * - `new undici.MockAgent()` - in-process mocking\n *\n * When omitted the process-global dispatcher (`getGlobalDispatcher()`)\n * is used, which is undici's default `Agent`.\n */\n readonly dispatcher?: Dispatcher;\n /** Maximum buffered response body size in bytes (default: 32 MiB). */\n readonly maximumResponseBodySize?: number;\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\n/**\n * Serialise the `body` option to a `Buffer` (or `null` for bodyless requests).\n * Returns the buffer AND the inferred Content-Type so callers can set the\n * header automatically.\n */\nfunction prepareBody(\n body: string | Uint8Array | Record<string, unknown> | null | undefined,\n): { buf: Buffer | null; inferredContentType: string | null } {\n if (body == null) return { buf: null, inferredContentType: null };\n if (body instanceof Uint8Array) {\n return { buf: Buffer.from(body.buffer, body.byteOffset, body.byteLength), inferredContentType: null };\n }\n if (typeof body === 'string') {\n return { buf: Buffer.from(body, 'utf8'), inferredContentType: null };\n }\n return {\n buf: Buffer.from(JSON.stringify(body), 'utf8'),\n inferredContentType: 'application/json',\n };\n}\n\n/**\n * Merge session-level default headers with per-request headers.\n * Per-request headers win on collision.\n * Injects Content-Length and Content-Type when a body is present.\n */\nfunction buildHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n body: Buffer | null,\n inferredContentType: string | null,\n): Record<string, string> {\n const merged: Record<string, string> = { ...defaults, ...(overrides ?? {}) };\n if (body !== null) {\n merged['content-length'] = String(body.length);\n if (!merged['content-type'] && inferredContentType !== null) {\n merged['content-type'] = inferredContentType;\n }\n }\n return merged;\n}\n\n/**\n * Normalise an undici response headers object\n * (`Record<string, string | string[]>`) to our `HttpResponse.headers` shape\n * (`Record<string, string | string[] | undefined>`).\n */\nfunction normaliseHeaders(\n h: Record<string, string | string[]>,\n): Record<string, string | string[] | undefined> {\n // The shapes are structurally compatible; we just widen the type.\n return h as Record<string, string | string[] | undefined>;\n}\n\nfunction assertBodySize(size: number, maximum: number): void {\n if (size > maximum) {\n throw new Error(`HTTP response body exceeds the ${maximum} byte limit.`);\n }\n}\n\n// ─── Abstract base ────────────────────────────────────────────────────────────\n\n/**\n * Holds the session-level options and exposes the convenience wrappers\n * (`get`, `post`, `delete`) that delegate to the abstract `request` method.\n *\n * Concrete subclasses only need to implement `request()` and `stream()`.\n */\nabstract class BaseUndiciClient implements IHttpClient {\n /** Default headers merged into every outgoing request. */\n protected readonly defaultHeaders: Record<string, string>;\n /** Session-level request timeout in milliseconds. */\n protected readonly defaultTimeout: number;\n /**\n * Shared undici Dispatcher. May be an Agent, Pool, Client, ProxyAgent, etc.\n * Defaults to undici's process-global agent when not specified.\n */\n protected readonly dispatcher: Dispatcher;\n protected readonly maximumResponseBodySize: number;\n\n constructor(options: HttpClientOptions = {}) {\n this.defaultHeaders = options.headers ?? {};\n this.defaultTimeout = options.timeout ?? 30_000;\n this.dispatcher = options.dispatcher ?? getGlobalDispatcher();\n this.maximumResponseBodySize = options.maximumResponseBodySize ?? 32 * 1024 * 1024;\n }\n\n // Convenience wrappers ──────────────────────────────────────────────────────\n\n get(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('GET', url, options);\n }\n\n post(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('POST', url, options);\n }\n\n delete(url: string, options?: RequestOptions): Promise<HttpResponse> {\n return this.request('DELETE', url, options);\n }\n\n // Abstract surface - each subclass provides its own undici primitive ────────\n\n abstract request(\n method: HttpMethod,\n url: string,\n options?: RequestOptions,\n ): Promise<HttpResponse>;\n\n abstract stream(\n method: HttpMethod,\n url: string,\n options?: RequestOptions,\n ): Promise<StreamResult>;\n}\n\n// ─── 1. RequestHttpClient ─────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.request()`.\n *\n * `undici.request` is the recommended high-level API for most use-cases.\n * It returns a Promise that resolves with `{ statusCode, headers, body }`\n * where `body` is an undici `BodyReadable` (a Node `Readable` subclass).\n *\n * For buffered responses (`request()`) we call `body.text()` to collect the\n * full response. For streaming responses (`stream()`) we return `body`\n * directly as the `StreamResult.body` Readable, giving the caller zero-copy\n * access to the response stream.\n *\n */\nexport class RequestHttpClient extends BaseUndiciClient {\n /**\n * Buffered request - collects the entire response body as a string.\n *\n * Timeout is implemented via undici's built-in `headersTimeout` /\n * `bodyTimeout` options rather than an external `setTimeout`.\n */\n override async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n const { statusCode, headers: respHeaders, body } = await undiciRequest(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n });\n\n const text = await body.text();\n assertBodySize(Buffer.byteLength(text), this.maximumResponseBodySize);\n\n return {\n status: statusCode,\n headers: normaliseHeaders(respHeaders as Record<string, string | string[]>),\n body: text,\n };\n }\n\n /**\n * Streaming request - returns the response body `Readable` without\n * buffering. Used by SSE and long-polling transports.\n *\n * The `abort()` method destroys the underlying socket and the body stream.\n */\n override async stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const { statusCode, headers: respHeaders, body } = await undiciRequest(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n // No bodyTimeout here - SSE connections are intentionally long-lived.\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n });\n\n return {\n statusCode,\n headers: normaliseHeaders(respHeaders as Record<string, string | string[]>),\n body: body as unknown as Readable,\n abort: () => body.destroy(),\n };\n }\n}\n\n// ─── 2. FetchHttpClient ───────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.fetch()`.\n *\n * `undici.fetch` is undici's WHATWG-compatible Fetch implementation.\n * It accepts the same options as the browser `fetch()` API, plus an\n * undici-specific `dispatcher` field for custom transport control.\n *\n * Useful when you need browser API compatibility (e.g., tests that run in\n * both Node and a browser-like environment) or when consuming WHATWG `Response`\n * helpers such as `res.json()` / `res.formData()`.\n *\n * For `stream()` we convert the WHATWG `ReadableStream<Uint8Array>` body to a\n * Node.js `Readable` via `Readable.fromWeb()` (Node 17+).\n */\nexport class FetchHttpClient extends BaseUndiciClient {\n override async request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const ac = new AbortController();\n const timeout = options.timeout ?? this.defaultTimeout;\n const timer = timeout > 0\n ? setTimeout(() => ac.abort(new Error(`HTTP request timed out after ${timeout} ms`)), timeout)\n : null;\n\n try {\n const res = await undiciFetch(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n signal: ac.signal,\n // undici-specific: override the dispatcher for this request.\n // undici's fetch type is defined in two conflicting locations\n // (undici-types bundled with @types/node AND undici's own .d.ts),\n // so the intersection cast doesn't satisfy either. The double-cast\n // via `unknown` sidesteps the conflict without losing safety: at\n // runtime undici.fetch() accepts exactly this shape.\n dispatcher: this.dispatcher,\n } as unknown as Parameters<typeof undiciFetch>[1]);\n\n const text = await res.text();\n assertBodySize(Buffer.byteLength(text), this.maximumResponseBodySize);\n if (timer !== null) clearTimeout(timer);\n\n // Convert Headers object to plain Record\n const respHeaders: Record<string, string | string[] | undefined> = {};\n res.headers.forEach((value, key) => { respHeaders[key] = value; });\n\n return { status: res.status, headers: respHeaders, body: text };\n } catch (err) {\n if (timer !== null) clearTimeout(timer);\n throw err;\n }\n }\n\n override async stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const ac = new AbortController();\n\n const res = await undiciFetch(url, {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n signal: ac.signal,\n dispatcher: this.dispatcher,\n } as unknown as Parameters<typeof undiciFetch>[1]);\n\n // Convert WHATWG ReadableStream → Node Readable\n const body = Readable.fromWeb(\n res.body as Parameters<typeof Readable.fromWeb>[0],\n );\n\n const respHeaders: Record<string, string | string[] | undefined> = {};\n res.headers.forEach((value, key) => { respHeaders[key] = value; });\n\n return {\n statusCode: res.status,\n headers: respHeaders,\n body,\n abort: () => { ac.abort(); body.destroy(); },\n };\n }\n}\n\n// ─── 3. StreamHttpClient ──────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.stream()`.\n *\n * `undici.stream` uses a *factory callback* pattern: you supply a function\n * that receives `{ statusCode, headers, body }` and must return a\n * `Writable` to which the response body is piped.\n *\n * This makes it ideal when you want to pipe response bytes directly to a\n * destination (e.g., a file, a transform, or a compression stream) without\n * ever holding the entire response in memory.\n *\n * For buffered `request()` we use a `PassThrough` as the sink and collect\n * its output. For streaming `stream()` we expose the PassThrough's\n * readable side as `StreamResult.body`.\n */\nexport class StreamHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n let statusCode = 0;\n let respHeaders: Record<string, string | string[]> = {};\n const chunks: Buffer[] = [];\n\n return undiciStream(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode: sc, headers: h }) => {\n statusCode = sc;\n respHeaders = h as Record<string, string | string[]>;\n\n // Sink that collects the response bytes\n const sink = new PassThrough();\n sink.on('data', (chunk: Buffer) => chunks.push(chunk));\n return sink;\n },\n ).then(() => ({\n status: statusCode,\n headers: normaliseHeaders(respHeaders),\n body: (() => {\n const body = Buffer.concat(chunks);\n assertBodySize(body.length, this.maximumResponseBodySize);\n return body.toString('utf8');\n })(),\n }));\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n return new Promise<StreamResult>((resolve, reject) => {\n // The PassThrough is the pipe target inside the factory AND the readable\n // we hand back to the caller - the same object plays both roles.\n const pt = new PassThrough();\n\n undiciStream(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode, headers: h }) => {\n resolve({\n statusCode,\n headers: normaliseHeaders(h as Record<string, string | string[]>),\n body: pt,\n abort: () => pt.destroy(),\n });\n // Return the same PassThrough as the writable sink.\n // undici pipes the response body into it; callers read from it.\n return pt;\n },\n ).catch((err: unknown) => {\n // Connection failed before headers: Promise has not resolved, so no\n // caller holds a reference to `pt`. Destroy it without an error arg\n // to avoid emitting an unhandled 'error' event on an orphaned stream.\n pt.destroy();\n reject(err);\n });\n });\n }\n}\n\n// ─── 4. PipelineHttpClient ────────────────────────────────────────────────────\n\n/**\n * HTTP client backed by `undici.pipeline()`.\n *\n * `undici.pipeline` returns a `stream.Duplex`:\n * - **Writable side**: the request body (write / pipe into it).\n * - **Readable side**: whatever your handler function *returns*.\n *\n * The handler receives `{ statusCode, headers, body }` and must return a\n * `Readable`. Whatever that readable emits becomes the duplex's output.\n *\n * Typical use: response transformation pipelines\n * `pipeline(url, opts, ({ body }) => body.pipe(gunzip()))`\n *\n * For `request()` we return the raw body from the handler, collect the duplex\n * output into a buffer, and resolve with the buffered string.\n *\n * For `stream()` we return the raw body from the handler and give the caller\n * the duplex's readable side directly - zero extra buffering.\n */\nexport class PipelineHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const timeout = options.timeout ?? this.defaultTimeout;\n\n return new Promise<HttpResponse>((resolve, reject) => {\n let statusCode = 0;\n let respHeaders: Record<string, string | string[]> = {};\n const chunks: Buffer[] = [];\n\n const duplex = undiciPipeline(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: timeout,\n bodyTimeout: timeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode: sc, headers: h, body }) => {\n statusCode = sc;\n respHeaders = h as Record<string, string | string[]>;\n // Return the body readable - it becomes the duplex output.\n return body;\n },\n );\n\n duplex.on('data', (chunk: Buffer) => chunks.push(chunk));\n duplex.on('end', () =>\n resolve({\n status: statusCode,\n headers: normaliseHeaders(respHeaders),\n body: (() => {\n const body = Buffer.concat(chunks);\n assertBodySize(body.length, this.maximumResponseBodySize);\n return body.toString('utf8');\n })(),\n }),\n );\n duplex.on('error', reject);\n\n // Signal end-of-request-body (required even for bodyless requests)\n if (buf !== null) {\n duplex.write(buf);\n }\n duplex.end();\n });\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n return new Promise<StreamResult>((resolve, reject) => {\n let resolved = false;\n\n // `duplex` is assigned by `undiciPipeline` (synchronously before any\n // async I/O), so the closure inside the handler can safely reference it.\n // eslint-disable-next-line prefer-const\n let duplex: ReturnType<typeof undiciPipeline>;\n\n duplex = undiciPipeline(\n url,\n {\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n dispatcher: this.dispatcher,\n },\n ({ statusCode, headers: h, body }) => {\n if (!resolved) {\n resolved = true;\n resolve({\n statusCode,\n headers: normaliseHeaders(h as Record<string, string | string[]>),\n // The duplex IS the readable - its output is the body.\n body: duplex as unknown as Readable,\n abort: () => duplex.destroy(),\n });\n }\n // Return body so pipeline routes it to the duplex's readable side.\n return body;\n },\n );\n\n duplex.on('error', (err: Error) => {\n if (!resolved) reject(err);\n });\n\n if (buf !== null) duplex.write(buf);\n duplex.end();\n });\n }\n}\n\n// ─── 5. DispatchHttpClient (DEFAULT) ─────────────────────────────────────────\n\n/**\n * HTTP client backed by `Dispatcher#dispatch()`.\n *\n * `dispatch` is the *lowest-level* undici API. It exposes the full\n * request/response lifecycle as a handler interface (undici 8+):\n *\n * onRequestStart → request is about to be sent; receives DispatchController\n * onResponseStart → response status + headers received\n * onResponseData → response body chunk\n * onResponseEnd → response fully consumed\n * onResponseError → error at any stage\n *\n * This gives you maximum control: you can abort mid-stream, transform\n * chunks on the fly, or implement custom back-pressure logic.\n *\n * Unlike the other clients, `DispatchHttpClient` *requires* a `Dispatcher`\n * (an `Agent`, `Pool`, or `Client` instance). If none is provided the\n * process-global agent is used.\n *\n * Note: `dispatcher.dispatch()` needs the URL split into `origin` + `path`\n * (for `Agent` / `Pool`) or just `path` (for `Client` whose origin is\n * already bound). We always pass `origin` for maximum compatibility.\n */\nexport class DispatchHttpClient extends BaseUndiciClient {\n override request(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<HttpResponse> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n\n const parsed = new URL(url);\n const timeout = options.timeout ?? this.defaultTimeout;\n\n return new Promise<HttpResponse>((resolve, reject) => {\n let statusCode = 0;\n let respHeaders: Record<string, string | string[] | undefined> = {};\n const chunks: Buffer[] = [];\n let responseSize = 0;\n let controller: Dispatcher.DispatchController | null = null;\n let settled = false;\n\n let timer: ReturnType<typeof setTimeout> | null = null;\n if (timeout > 0) {\n timer = setTimeout(() => {\n /* istanbul ignore next -- timer is cleared on every settled path */\n if (settled) return;\n settled = true;\n const error = new Error(`HTTP request timed out after ${timeout} ms`);\n controller?.abort(error);\n reject(error);\n }, timeout);\n }\n\n const clearTimer = (): void => {\n if (timer !== null) { clearTimeout(timer); timer = null; }\n };\n\n this.dispatcher.dispatch(\n {\n origin: parsed.origin,\n path: parsed.pathname + parsed.search,\n method,\n headers,\n ...(buf !== null && { body: buf }),\n },\n {\n onRequestStart: (ctrl: Dispatcher.DispatchController, _context: unknown): void => {\n controller = ctrl;\n },\n\n onResponseError: (_controller: Dispatcher.DispatchController, err: Error): void => {\n clearTimer();\n /* istanbul ignore next -- undici does not end after reporting an error */\n if (settled) return;\n settled = true;\n reject(err);\n },\n\n onResponseStart: (\n _controller: Dispatcher.DispatchController,\n sc: number,\n headers: Record<string, string | string[] | undefined>,\n ): void => {\n statusCode = sc;\n respHeaders = headers;\n },\n\n onResponseData: (_controller: Dispatcher.DispatchController, chunk: Buffer): void => {\n chunks.push(Buffer.from(chunk));\n responseSize += chunk.length;\n if (responseSize > this.maximumResponseBodySize) {\n _controller.abort(new Error(`HTTP response body exceeds the ${this.maximumResponseBodySize} byte limit.`));\n }\n },\n\n onResponseEnd: (_controller: Dispatcher.DispatchController, _trailers: Record<string, string | string[] | undefined>): void => {\n clearTimer();\n /* istanbul ignore next -- undici does not end after reporting an error */\n if (settled) return;\n settled = true;\n resolve({\n status: statusCode,\n headers: respHeaders,\n body: Buffer.concat(chunks).toString('utf8'),\n });\n },\n } satisfies Dispatcher.DispatchHandler,\n );\n });\n }\n\n override stream(\n method: HttpMethod,\n url: string,\n options: RequestOptions = {},\n ): Promise<StreamResult> {\n const { buf, inferredContentType } = prepareBody(options.body);\n const headers = buildHeaders(\n this.defaultHeaders, options.headers, buf, inferredContentType,\n );\n const parsed = new URL(url);\n\n return new Promise<StreamResult>((resolve, reject) => {\n let resolved = false;\n // PassThrough exposes a readable side to the caller and accepts\n // body chunks pushed to it from the onResponseData handler.\n const pt = new PassThrough();\n\n let controller: Dispatcher.DispatchController | null = null;\n\n this.dispatcher.dispatch(\n {\n origin: parsed.origin,\n path: parsed.pathname + parsed.search,\n method,\n headers,\n ...(buf !== null && { body: buf }),\n headersTimeout: options.timeout ?? this.defaultTimeout,\n },\n {\n onRequestStart: (ctrl: Dispatcher.DispatchController, _context: unknown): void => {\n controller = ctrl;\n },\n\n onResponseError: (_ctrl: Dispatcher.DispatchController, err: Error): void => {\n if (!resolved) {\n // Promise not yet resolved: reject it. The PassThrough stream has\n // not been handed to the caller yet, so destroy it silently to\n // avoid an unhandled 'error' event on a stream nobody is reading.\n resolved = true;\n pt.destroy();\n reject(err);\n } else {\n // Response headers were already delivered; propagate the error\n // through the stream so the caller's reader sees it.\n pt.destroy(err);\n }\n },\n\n onResponseStart: (\n _ctrl: Dispatcher.DispatchController,\n statusCode: number,\n headers: Record<string, string | string[] | undefined>,\n ): void => {\n if (!resolved) {\n resolved = true;\n resolve({\n statusCode,\n headers,\n body: pt,\n abort: () => {\n controller?.abort(new Error('Stream aborted'));\n pt.destroy();\n },\n });\n }\n },\n\n onResponseData: (_ctrl: Dispatcher.DispatchController, chunk: Buffer): void => {\n if (!pt.write(chunk)) {\n controller?.pause();\n pt.once('drain', () => controller?.resume());\n }\n },\n\n onResponseEnd: (_ctrl: Dispatcher.DispatchController, _trailers: Record<string, string | string[] | undefined>): void => {\n pt.end();\n },\n } satisfies Dispatcher.DispatchHandler,\n );\n });\n }\n}\n\n// ─── HttpClient - backward-compat alias ──────────────────────────────────────\n\n/**\n * `HttpClient` is an alias for `DispatchHttpClient` (the default).\n *\n * Existing code that `import { HttpClient }` continues to work without\n * modification. `new HttpClient(opts)` behaves identically to\n * `new DispatchHttpClient(opts)`.\n */\nexport { DispatchHttpClient as HttpClient };\n","/**\n * constants.ts\n *\n * All SignalR protocol constants, enumerations, and timing defaults.\n * Uses `as const satisfies` (TS 4.9+) so values carry their narrow literal\n * types while being verified against a constraint at compile time.\n */\n\n// ─── MessageType ──────────────────────────────────────────────────────────────\n// Each value doubles as both a runtime constant and a narrow numeric literal\n// type (used in the discriminated-union HubMessage in messages.ts).\n\nexport const MessageType = Object.freeze({\n Invocation: 1,\n StreamItem: 2,\n Completion: 3,\n StreamInvocation: 4,\n CancelInvocation: 5,\n Ping: 6,\n Close: 7,\n} as const satisfies Record<string, number>);\n\n/** Union of all valid message type numbers. */\nexport type MessageTypeValue = (typeof MessageType)[keyof typeof MessageType];\n\n// ─── HubConnectionState ───────────────────────────────────────────────────────\n\nexport const HubConnectionState = Object.freeze({\n Disconnected: 'Disconnected',\n Connecting: 'Connecting',\n Connected: 'Connected',\n Disconnecting: 'Disconnecting',\n Reconnecting: 'Reconnecting',\n} as const satisfies Record<string, string>);\n\n/** Union of all valid connection state strings. */\nexport type HubConnectionState = (typeof HubConnectionState)[keyof typeof HubConnectionState];\n\n// ─── LogLevel ─────────────────────────────────────────────────────────────────\n\nexport const LogLevel = {\n Trace: 0,\n Debug: 1,\n Information: 2,\n Warning: 3,\n Error: 4,\n Critical: 5,\n None: 6,\n} as const satisfies Record<string, number>;\n\nexport type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];\n\n// ─── HttpTransportType ────────────────────────────────────────────────────────\n\nexport const HttpTransportType = {\n None: 0,\n WebSockets: 1,\n ServerSentEvents: 2,\n LongPolling: 4,\n} as const satisfies Record<string, number>;\n\n/** Bitmask of enabled transports - values can be OR-ed together. */\nexport type HttpTransportType = (typeof HttpTransportType)[keyof typeof HttpTransportType];\n\n// ─── TransferFormat ───────────────────────────────────────────────────────────\n\nexport const TransferFormat = {\n Text: 1,\n Binary: 2,\n} as const satisfies Record<string, number>;\n\nexport type TransferFormat = (typeof TransferFormat)[keyof typeof TransferFormat];\n\n// ─── Protocol constants ───────────────────────────────────────────────────────\n\n/** ASCII 30 - the byte that terminates every SignalR JSON message. */\nexport const RECORD_SEPARATOR = '\\x1e' as const;\n\n/** Negotiate version we advertise to the server. */\nexport const NEGOTIATE_VERSION = 1 as const;\n\n// ─── Timing defaults ──────────────────────────────────────────────────────────\n\nexport const DEFAULT_TIMEOUT_IN_MS = 30_000 as const;\nexport const DEFAULT_PING_INTERVAL_IN_MS = 15_000 as const;\nexport const DEFAULT_SERVER_TIMEOUT_IN_MS = 30_000 as const;\n","/**\n * messages.ts\n *\n * Full discriminated-union type definitions for every SignalR hub protocol\n * message. The `type` field on each interface carries a numeric literal type\n * derived from the `MessageType` constants so TypeScript narrows correctly\n * inside `switch` / `if` statements.\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport type { MessageType } from './constants.js';\n\n// ─── Branding ─────────────────────────────────────────────────────────────────\n\ndeclare const __invocationIdBrand: unique symbol;\n\n/**\n * Opaque wrapper around `string` for invocation IDs.\n * Prevents mixing arbitrary strings with IDs at the type level.\n */\nexport type InvocationId = string & { readonly [__invocationIdBrand]: void };\n\n/** Cast a plain string to an InvocationId (only used inside the library). */\nexport function toInvocationId(s: string): InvocationId {\n return s as InvocationId;\n}\n\n// ─── Common metadata ──────────────────────────────────────────────────────────\n\n/** Optional headers that may appear on any hub message. */\nexport type MessageHeaders = Readonly<Record<string, string>>;\n\ninterface BaseMessage {\n readonly headers?: MessageHeaders;\n}\n\n// ─── Individual message shapes ────────────────────────────────────────────────\n\ntype MT = typeof MessageType;\n\n/** Type 1 - Server→Client or Client→Server method call. */\nexport interface InvocationMessage extends BaseMessage {\n readonly type: MT['Invocation'];\n /** Absent on fire-and-forget invocations. */\n readonly invocationId?: InvocationId;\n readonly target: string;\n readonly arguments: readonly unknown[];\n readonly streamIds?: readonly string[];\n}\n\n/** Type 2 - One item from a server-streaming method. */\nexport interface StreamItemMessage extends BaseMessage {\n readonly type: MT['StreamItem'];\n readonly invocationId: InvocationId;\n readonly item: unknown;\n}\n\n/** Type 3 - Terminal result or error for an invocation / stream. */\nexport interface CompletionMessage extends BaseMessage {\n readonly type: MT['Completion'];\n readonly invocationId: InvocationId;\n readonly error?: string;\n readonly result?: unknown;\n}\n\n/** Type 4 - Client initiates a server-streaming call. */\nexport interface StreamInvocationMessage extends BaseMessage {\n readonly type: MT['StreamInvocation'];\n readonly invocationId: InvocationId;\n readonly target: string;\n readonly arguments: readonly unknown[];\n readonly streamIds?: readonly string[];\n}\n\n/** Type 5 - Client cancels an outstanding server stream. */\nexport interface CancelInvocationMessage extends BaseMessage {\n readonly type: MT['CancelInvocation'];\n readonly invocationId: InvocationId;\n}\n\n/** Type 6 - Keep-alive ping; expects no response from the other side. */\nexport interface PingMessage extends BaseMessage {\n readonly type: MT['Ping'];\n}\n\n/** Type 7 - Graceful close notification from the server. */\nexport interface CloseMessage extends BaseMessage {\n readonly type: MT['Close'];\n readonly error?: string;\n readonly allowReconnect?: boolean;\n}\n\n// ─── Union ────────────────────────────────────────────────────────────────────\n\n/** Exhaustive discriminated union of all SignalR hub protocol messages. */\nexport type HubMessage =\n | InvocationMessage\n | StreamItemMessage\n | CompletionMessage\n | StreamInvocationMessage\n | CancelInvocationMessage\n | PingMessage\n | CloseMessage;\n\n// ─── Utility: exhaustiveness helper ──────────────────────────────────────────\n\n/**\n * Asserts a code path is unreachable at compile time.\n * Use at the `default` branch of a `switch` over `HubMessage['type']`.\n */\nexport function assertNever(_x: never, label?: string): never {\n throw new Error(`Unexpected value${label ? ` for ${label}` : ''}: ${JSON.stringify(_x)}`);\n}\n\n// ─── Type guards ─────────────────────────────────────────────────────────────\n\nexport function isInvocationMessage(msg: HubMessage): msg is InvocationMessage {\n return msg.type === 1;\n}\n\nexport function isStreamItemMessage(msg: HubMessage): msg is StreamItemMessage {\n return msg.type === 2;\n}\n\nexport function isCompletionMessage(msg: HubMessage): msg is CompletionMessage {\n return msg.type === 3;\n}\n\nexport function isStreamInvocationMessage(msg: HubMessage): msg is StreamInvocationMessage {\n return msg.type === 4;\n}\n\nexport function isCancelInvocationMessage(msg: HubMessage): msg is CancelInvocationMessage {\n return msg.type === 5;\n}\n\nexport function isPingMessage(msg: HubMessage): msg is PingMessage {\n return msg.type === 6;\n}\n\nexport function isCloseMessage(msg: HubMessage): msg is CloseMessage {\n return msg.type === 7;\n}\n","/**\n * json-hub-protocol.ts\n *\n * Implements the SignalR Hub Protocol over JSON (version 1).\n *\n * Wire format: every message is JSON followed by ASCII 0x1e (RECORD_SEPARATOR).\n * A single transport payload may contain multiple messages.\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport { MessageType, TransferFormat, RECORD_SEPARATOR } from '../constants.js';\nimport type { IHubProtocol, ILogger } from '../interfaces.js';\nimport {\n type HubMessage,\n type InvocationMessage,\n type StreamInvocationMessage,\n type CancelInvocationMessage,\n type CompletionMessage,\n type StreamItemMessage,\n type PingMessage,\n type CloseMessage,\n type InvocationId,\n toInvocationId,\n} from '../messages.js';\n\n// ─── Handshake constants ──────────────────────────────────────────────────────\n\nexport const HANDSHAKE_REQUEST =\n JSON.stringify({ protocol: 'json', version: 1 }) + RECORD_SEPARATOR;\n\nexport interface HandshakeResponse {\n readonly error?: string;\n readonly minorVersion?: number;\n}\n\nexport interface HandshakeParseResult {\n /** Remainder of the input string after the handshake record (may be non-empty). */\n readonly remainder: string;\n}\n\n/**\n * Parse the first record from `data` as the server handshake response.\n * @throws {Error} if the record separator is missing or the server returned an error.\n */\nexport function parseHandshakeResponse(data: string): HandshakeParseResult {\n const idx = data.indexOf(RECORD_SEPARATOR);\n if (idx === -1) {\n throw new Error('Handshake response is missing the record separator.');\n }\n\n const raw: string = data.slice(0, idx);\n const response: HandshakeResponse = JSON.parse(raw) as HandshakeResponse;\n\n if (response.error) {\n throw new Error(`Server rejected the handshake with the error: \"${response.error}\"`);\n }\n\n return { remainder: data.slice(idx + 1) };\n}\n\n// ─── Raw message shape (before validation/narrowing) ─────────────────────────\n\ninterface RawMessage {\n type: unknown;\n invocationId?: unknown;\n target?: unknown;\n arguments?: unknown;\n streamIds?: unknown;\n item?: unknown;\n result?: unknown;\n error?: unknown;\n allowReconnect?: unknown;\n headers?: unknown;\n}\n\n// ─── Protocol class ───────────────────────────────────────────────────────────\n\nexport class JsonHubProtocol implements IHubProtocol {\n readonly name = 'json' as const;\n readonly version = 1 as const;\n readonly transferFormat = TransferFormat.Text;\n\n // ─── IHubProtocol: parseMessages ─────────────────────────────────────\n\n parseMessages(input: string | ArrayBuffer, logger: ILogger): HubMessage[] {\n const text = typeof input === 'string' ? input : new TextDecoder().decode(input);\n if (!text) return [];\n\n const messages: HubMessage[] = [];\n const parts = text.split(RECORD_SEPARATOR);\n\n for (const part of parts) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n\n let raw: RawMessage;\n try {\n raw = JSON.parse(trimmed) as RawMessage;\n } catch (e) {\n throw new Error(`Error parsing message: ${(e as Error).message}. Raw value: \"${trimmed}\"`);\n }\n\n const msg = this.#coerce(raw);\n if (msg !== null) {\n messages.push(msg);\n } else {\n logger.log(3 /* Warning */, `Ignoring message with unknown type ${String(raw.type)}.`);\n }\n }\n\n return messages;\n }\n\n // ─── IHubProtocol: writeMessage ───────────────────────────────────────\n\n writeMessage(message: HubMessage): string {\n return JSON.stringify(message) + RECORD_SEPARATOR;\n }\n\n // ─── Coercion / narrowing ─────────────────────────────────────────────\n\n /**\n * Validate and narrow a raw parsed object into a typed `HubMessage`.\n * Returns `null` for unknown types (not an error - new protocol versions\n * may add types we don't know about).\n */\n #coerce(raw: RawMessage): HubMessage | null {\n const type = raw.type;\n if (typeof type !== 'number') {\n throw new Error(`Invalid message: 'type' must be a number, got ${JSON.stringify(type)}.`);\n }\n\n switch (type) {\n case MessageType.Invocation:\n return this.#coerceInvocation(raw);\n case MessageType.StreamItem:\n return this.#coerceStreamItem(raw);\n case MessageType.Completion:\n return this.#coerceCompletion(raw);\n case MessageType.StreamInvocation:\n return this.#coerceStreamInvocation(raw);\n case MessageType.CancelInvocation:\n return this.#coerceCancelInvocation(raw);\n case MessageType.Ping:\n return this.#coercePing();\n case MessageType.Close:\n return this.#coerceClose(raw);\n default:\n return null;\n }\n }\n\n #coerceInvocation(raw: RawMessage): InvocationMessage {\n if (typeof raw.target !== 'string') {\n throw new Error(\"Invalid Invocation message: 'target' must be a string.\");\n }\n if (!Array.isArray(raw.arguments)) {\n throw new Error(\"Invalid Invocation message: 'arguments' must be an array.\");\n }\n return {\n type: MessageType.Invocation,\n target: raw.target,\n arguments: raw.arguments as unknown[],\n ...(raw.invocationId != null && { invocationId: parseInvocationId(raw.invocationId) }),\n ...(raw.streamIds != null && { streamIds: parseStreamIds(raw.streamIds) }),\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n #coerceStreamItem(raw: RawMessage): StreamItemMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid StreamItem message: 'invocationId' is required.\");\n }\n return {\n type: MessageType.StreamItem,\n invocationId: parseInvocationId(raw.invocationId),\n item: raw.item,\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n #coerceCompletion(raw: RawMessage): CompletionMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid Completion message: 'invocationId' is required.\");\n }\n const hasResult = Object.prototype.hasOwnProperty.call(raw, 'result');\n if (raw.error != null && hasResult) {\n throw new Error(\"Invalid Completion message: 'error' and 'result' are mutually exclusive.\");\n }\n return {\n type: MessageType.Completion,\n invocationId: parseInvocationId(raw.invocationId),\n ...(raw.error != null && { error: String(raw.error) }),\n ...(hasResult && { result: raw.result }),\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n #coerceStreamInvocation(raw: RawMessage): StreamInvocationMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid StreamInvocation message: 'invocationId' is required.\");\n }\n if (typeof raw.target !== 'string') {\n throw new Error(\"Invalid StreamInvocation message: 'target' must be a string.\");\n }\n if (!Array.isArray(raw.arguments)) {\n throw new Error(\"Invalid StreamInvocation message: 'arguments' must be an array.\");\n }\n return {\n type: MessageType.StreamInvocation,\n invocationId: parseInvocationId(raw.invocationId),\n target: raw.target,\n arguments: raw.arguments as unknown[],\n ...(raw.streamIds != null && { streamIds: parseStreamIds(raw.streamIds) }),\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n #coerceCancelInvocation(raw: RawMessage): CancelInvocationMessage {\n if (raw.invocationId == null) {\n throw new Error(\"Invalid CancelInvocation message: 'invocationId' is required.\");\n }\n return {\n type: MessageType.CancelInvocation,\n invocationId: parseInvocationId(raw.invocationId),\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n #coercePing(): PingMessage {\n return { type: MessageType.Ping };\n }\n\n #coerceClose(raw: RawMessage): CloseMessage {\n if (raw.allowReconnect != null && typeof raw.allowReconnect !== 'boolean') {\n throw new Error(\"Invalid Close message: 'allowReconnect' must be a boolean.\");\n }\n return {\n type: MessageType.Close,\n ...(raw.error != null && { error: String(raw.error) }),\n ...(raw.allowReconnect != null && { allowReconnect: raw.allowReconnect }),\n ...(raw.headers != null && { headers: parseHeaders(raw.headers) }),\n };\n }\n\n // ─── Static message factories ─────────────────────────────────────────\n\n static invocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n /**\n * Fire-and-forget (no `invocationId` → server won't send a Completion).\n */\n static send(\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static streamInvocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): StreamInvocationMessage {\n return {\n type: MessageType.StreamInvocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static cancelInvocation(invocationId: InvocationId): CancelInvocationMessage {\n return { type: MessageType.CancelInvocation, invocationId };\n }\n\n static streamItem(invocationId: InvocationId, item: unknown): StreamItemMessage {\n return { type: MessageType.StreamItem, invocationId, item };\n }\n\n static completion(\n invocationId: InvocationId,\n result: unknown,\n error: string | null,\n ): CompletionMessage {\n return {\n type: MessageType.Completion,\n invocationId,\n ...(error != null && { error }),\n ...(result != null && { result }),\n };\n }\n\n static ping(): PingMessage {\n return { type: MessageType.Ping };\n }\n}\n\nfunction parseInvocationId(value: unknown): InvocationId {\n if (typeof value !== 'string') throw new Error(\"Invalid message: 'invocationId' must be a string.\");\n return toInvocationId(value);\n}\n\nfunction parseStreamIds(value: unknown): string[] {\n if (!Array.isArray(value) || !value.every((entry) => typeof entry === 'string')) {\n throw new Error(\"Invalid message: 'streamIds' must be an array of strings.\");\n }\n return value;\n}\n\nfunction parseHeaders(value: unknown): Record<string, string> {\n if (value === null || typeof value !== 'object' || Array.isArray(value) ||\n !Object.values(value).every((entry) => typeof entry === 'string')) {\n throw new Error(\"Invalid message: 'headers' must be an object containing string values.\");\n }\n return value as Record<string, string>;\n}\n","/**\n * websocket-transport.ts\n *\n * SignalR WebSocket transport - rewritten to use undici's built-in\n * WHATWG-compatible `WebSocket` implementation.\n *\n * Why undici WebSocket instead of the hand-rolled RFC 6455 client?\n * ─────────────────────────────────────────────────────────────────\n * • undici is the HTTP engine Node.js core ships with (≥ v18).\n * • Its WebSocket implementation passes the Autobahn test suite.\n * • It accepts the same `Dispatcher` used by the HTTP clients, so the\n * entire SignalR session (negotiate, handshake, upgrade) shares a single\n * connection pool / proxy config.\n * • It supports custom headers on the upgrade request (needed for auth\n * and extra headers), which the browser WebSocket API does not.\n *\n * undici WebSocket quirks in Node.js\n * ────────────────────────────────────\n * • The constructor signature is:\n * new WebSocket(url, { headers?, dispatcher?, protocols? })\n * The `headers` and `dispatcher` fields are undici extensions not in the\n * WHATWG spec.\n * • `MessageEvent.data` type depends on `ws.binaryType`:\n * 'arraybuffer' (what we set) → ArrayBuffer\n * 'blob' → Blob\n * We set `binaryType = 'arraybuffer'` and convert ArrayBuffer → Buffer on\n * receipt. ('nodebuffer' is a valid undici runtime value but is absent from\n * the WHATWG BinaryType union in undici's TypeScript declarations.)\n * • `CloseEvent.code` / `.reason` behave identically to the browser.\n */\n\nimport { WebSocket } from 'undici';\nimport type { Dispatcher } from 'undici';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\n\n// ─── ReadyState constants (mirrors window.WebSocket) ─────────────────────────\n\nexport const WebSocketReadyState = Object.freeze({\n Connecting: 0,\n Open: 1,\n Closing: 2,\n Closed: 3,\n} as const satisfies Record<string, number>);\n\nexport type WebSocketReadyState =\n (typeof WebSocketReadyState)[keyof typeof WebSocketReadyState];\n\n// ─── Transport implementation ─────────────────────────────────────────────────\n\nexport class WebSocketTransport implements ITransport {\n readonly name = 'WebSockets' as const;\n\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n readonly #dispatcher: Dispatcher | undefined;\n\n #ws: WebSocket | null = null;\n #onreceive: ((data: string | Uint8Array) => void) | null = null;\n #pendingMessages: Array<string | Uint8Array> = [];\n\n onclose: ((error?: Error) => void) | null = null;\n\n get onreceive(): ((data: string | Uint8Array) => void) | null {\n return this.#onreceive;\n }\n\n set onreceive(handler: ((data: string | Uint8Array) => void) | null) {\n this.#onreceive = handler;\n /* istanbul ignore else -- HubConnection installs a receiver after connect */\n if (handler) {\n const pending = this.#pendingMessages;\n this.#pendingMessages = [];\n for (const message of pending) {\n /* istanbul ignore next -- requires a server frame in the connect/onreceive microtask gap */\n handler(message);\n }\n }\n }\n\n /**\n * @param accessTokenFactory Async factory for Bearer tokens, or null.\n * @param logger Logger instance.\n * @param extraHeaders Headers forwarded on every upgrade request.\n * @param dispatcher Optional undici Dispatcher (Agent/Pool/Client/\n * ProxyAgent). When omitted, undici's default\n * global agent is used. Pass the same dispatcher\n * used by your HTTP clients to share the pool.\n */\n constructor(\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n dispatcher?: Dispatcher,\n ) {\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n this.#dispatcher = dispatcher;\n }\n\n async connect(url: string, _transferFormat: TransferFormat): Promise<void> {\n this.#logger.log(LogLevel.Trace, `(WebSockets transport) Connecting to ${url}.`);\n\n // ── Build headers ───────────────────────────────────────────────────────\n const headers: Record<string, string> = { ...this.#extraHeaders };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n // ── Convert http(s) → ws(s) ─────────────────────────────────────────────\n const wsUrl = url.replace(/^http/, 'ws');\n\n // ── Open the WebSocket ──────────────────────────────────────────────────\n // undici's WebSocket constructor accepts headers + dispatcher as its\n // second argument. These are undici-specific extensions to the spec.\n const ws = new WebSocket(wsUrl, {\n headers,\n ...(this.#dispatcher !== undefined && { dispatcher: this.#dispatcher }),\n } as ConstructorParameters<typeof WebSocket>[1]);\n\n this.#ws = ws;\n\n // Keep binary frames as ArrayBuffer. 'nodebuffer' works at runtime but\n // is absent from the WHATWG BinaryType union in undici's type declarations,\n // so 'arraybuffer' is used here and converted to Buffer on receipt.\n ws.binaryType = 'arraybuffer';\n\n // Servers may send the SignalR handshake response immediately after the\n // WebSocket opens. Listen before awaiting `open`, and queue those frames\n // until HubConnection installs its receiver after connect() resolves.\n ws.addEventListener('message', (event) => {\n const data = (event as Event & { data: unknown }).data;\n const message = typeof data === 'string' ? data : Buffer.from(data as ArrayBuffer);\n this.#logger.log(LogLevel.Trace, typeof message === 'string'\n ? `(WebSockets transport) Received text (${message.length} chars).`\n : `(WebSockets transport) Received binary (${message.length} bytes).`);\n if (this.#onreceive) this.#onreceive(message);\n else this.#pendingMessages.push(message);\n });\n\n // ── Wait for the socket to be open before resolving ─────────────────────\n // We wrap the open/error events in a Promise so `connect()` only resolves\n // once the TCP + TLS + WebSocket handshake is fully complete.\n await new Promise<void>((resolve, reject) => {\n const cleanup = (): void => {\n ws.removeEventListener('open', onOpen);\n ws.removeEventListener('error', onError);\n };\n const onOpen = (): void => {\n cleanup();\n this.#logger.log(LogLevel.Information, '(WebSockets transport) Connected.');\n resolve();\n };\n\n const onError = (event: Event): void => {\n cleanup();\n // ErrorEvent is a browser DOM global absent from Node.js lib targets.\n // Cast to a structural equivalent to access `.error` / `.message`.\n const e = event as Event & { error?: unknown; message?: string };\n let err: Error;\n if (e.error instanceof Error) {\n // undici sometimes wraps the real network error (e.g. ECONNREFUSED)\n // inside `error.cause` and leaves `error.message` as an empty string.\n // Prefer the cause when the outer message is empty so callers see a\n // meaningful message (ECONNREFUSED, etc.) rather than ''.\n err = e.error.message\n ? e.error\n : (e.error.cause instanceof Error\n ? e.error.cause\n : new Error('WebSocket connection failed'));\n } else {\n err = new Error(String(e.message ?? 'WebSocket error'));\n }\n this.#logger.log(LogLevel.Error, `(WebSockets transport) Error during connect: ${err.message}`);\n this.#ws = null;\n ws.close();\n reject(err);\n };\n ws.addEventListener('open', onOpen);\n ws.addEventListener('error', onError);\n });\n\n // ── Wire ongoing event handlers (after open) ─────────────────────────────\n\n // CloseEvent is a browser DOM global absent from Node.js lib targets.\n // Cast to a structural equivalent to access `.code` / `.reason`.\n ws.addEventListener('close', (event) => {\n const closeEvent = event as Event & { code: number; reason: string };\n this.#logger.log(LogLevel.Information,\n `(WebSockets transport) Socket closed (code=${closeEvent.code}).`);\n // Only call onclose for unexpected closures (not our own stop() call).\n if (this.#ws !== null) {\n this.#ws = null;\n this.onclose?.();\n }\n });\n\n ws.addEventListener('error', (event) => {\n // Errors after the initial open.\n // Same structural-cast pattern as above: ErrorEvent not in Node lib.\n if (ws.readyState !== WebSocket.CONNECTING) {\n const e = event as Event & { error?: unknown; message?: string };\n const err = e.error instanceof Error\n ? e.error\n : new Error(String(e.message ?? 'WebSocket error'));\n this.#logger.log(LogLevel.Error, `(WebSockets transport) Error: ${err.message}`);\n // Null #ws BEFORE calling onclose so the 'close' event handler that\n // fires next sees this.#ws === null and does not call onclose a second\n // time (which would start two concurrent reconnect loops).\n if (this.#ws !== null) {\n this.#ws = null;\n this.onclose?.(err);\n }\n }\n });\n }\n\n send(data: string | Uint8Array): Promise<void> {\n if (!this.#ws || this.#ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error('WebSocket is not open.'));\n }\n try {\n // undici's WebSocket.send() accepts string | ArrayBufferLike |\n // ArrayBufferView | Blob. Uint8Array satisfies ArrayBufferView.\n this.#ws.send(data);\n return Promise.resolve();\n /* istanbul ignore next - ws.send() on an already-open socket does not\n throw synchronously; this catch is a belt-and-suspenders fallback. */\n } catch (err) {\n return Promise.reject(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n stop(): Promise<void> {\n if (this.#ws) {\n const ws = this.#ws;\n this.#ws = null; // clear BEFORE close so the close handler skips onclose\n ws.close(1000, 'Normal closure');\n }\n return Promise.resolve();\n }\n}\n","/**\n * sse-transport.ts\n *\n * SignalR transport using Server-Sent Events (SSE) for receiving and\n * HTTP POST for sending.\n *\n * SSE spec: https://html.spec.whatwg.org/multipage/server-sent-events.html\n *\n * Updated to use the new StreamResult shape from http-client.ts:\n * result.body - Node Readable carrying the SSE byte stream\n * result.abort - cancels the in-flight request (replaces req.destroy())\n */\n\nimport type { IHttpClient } from '../interfaces.js';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\n\nexport class ServerSentEventsTransport implements ITransport {\n readonly name = 'ServerSentEvents' as const;\n\n readonly #httpClient: IHttpClient;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n\n #url: string | null = null;\n #abort: (() => void) | null = null; // replaces the old ClientRequest handle\n #sseBuffer: string = '';\n\n onreceive: ((data: string | Uint8Array) => void) | null = null;\n onclose: ((error?: Error) => void) | null = null;\n\n constructor(\n httpClient: IHttpClient,\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n ) {\n this.#httpClient = httpClient;\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n }\n\n async connect(url: string, transferFormat: TransferFormat): Promise<void> {\n if (transferFormat === TransferFormat.Binary) {\n throw new Error('The Server-Sent Events transport only supports the Text transfer format.');\n }\n\n this.#logger.log(LogLevel.Trace, `(SSE transport) Connecting to ${url}.`);\n this.#url = url;\n\n const headers: Record<string, string> = {\n Accept: 'text/event-stream',\n ...this.#extraHeaders,\n };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const result = await this.#httpClient.stream('GET', url, { headers });\n\n if (result.statusCode !== 200) {\n // Attach a no-op error handler before destroying the body to prevent an\n // unhandled 'error' event if the underlying stream emits one on abort.\n result.body.on('error', () => {});\n result.abort();\n throw new Error(\n `Unexpected status code ${result.statusCode} from SSE endpoint.`,\n );\n }\n\n // Store the abort handle so stop() can cancel the long-lived GET\n this.#abort = result.abort;\n\n // The body is a Node Readable; setEncoding converts chunks to strings\n result.body.setEncoding('utf8');\n\n result.body.on('data', (chunk: string) => this.#onData(chunk));\n result.body.on('end', () => {\n this.#logger.log(LogLevel.Information, '(SSE transport) EventSource closed.');\n this.#abort = null;\n this.onclose?.();\n });\n result.body.on('error', (err: Error) => {\n this.#logger.log(LogLevel.Error, `(SSE transport) Stream error: ${err.message}`);\n this.#abort = null;\n this.onclose?.(err);\n });\n\n this.#logger.log(LogLevel.Information, '(SSE transport) Connected.');\n }\n\n async send(data: string | Uint8Array): Promise<void> {\n if (!this.#url) throw new Error('SSE transport is not connected.');\n\n const headers: Record<string, string> = {\n 'Content-Type': typeof data === 'string'\n ? 'text/plain;charset=UTF-8'\n : 'application/octet-stream',\n ...this.#extraHeaders,\n };\n\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const result = await this.#httpClient.post(this.#url, { headers, body: data });\n\n if (result.status < 200 || result.status >= 300) {\n throw new Error(`SSE send failed with status ${result.status}.`);\n }\n }\n\n stop(): Promise<void> {\n if (this.#abort) {\n this.#abort();\n this.#abort = null;\n }\n return Promise.resolve();\n }\n\n // ─── SSE parser ───────────────────────────────────────────────────────────\n\n #onData(chunk: string): void {\n this.#sseBuffer += chunk;\n\n let boundary: number;\n while ((boundary = findEventBoundary(this.#sseBuffer)) !== -1) {\n const block = this.#sseBuffer.slice(0, boundary);\n this.#sseBuffer = this.#sseBuffer.slice(boundary).replace(/^[\\r\\n]+/, '');\n this.#dispatchEvent(block);\n }\n }\n\n #dispatchEvent(block: string): void {\n const lines = block.split(/\\r?\\n/);\n const dataParts: string[] = [];\n\n for (const line of lines) {\n if (line.startsWith('data:')) {\n dataParts.push(line.slice(5).replace(/^ /, ''));\n }\n // event:, id:, retry: are intentionally ignored by SignalR's SSE\n }\n\n if (dataParts.length === 0) return;\n\n const message = dataParts.join('\\n');\n this.#logger.log(LogLevel.Trace, `(SSE transport) Received data: ${message}`);\n this.onreceive?.(message);\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction findEventBoundary(str: string): number {\n const i1 = str.indexOf('\\n\\n');\n const i2 = str.indexOf('\\r\\n\\r\\n');\n if (i1 === -1 && i2 === -1) return -1;\n if (i1 === -1) return i2 + 4;\n if (i2 === -1) return i1 + 2;\n return Math.min(i1 + 2, i2 + 4);\n}\n","/**\n * long-polling-transport.ts\n *\n * SignalR Long-Polling transport.\n * HTTP GET (hangs until data arrives) → receive\n * HTTP POST → send\n * HTTP DELETE → disconnect\n *\n * Updated to depend on IHttpClient rather than the concrete HttpClient class\n * so any of the five undici-backed client implementations can be injected.\n */\n\nimport type { IHttpClient } from '../interfaces.js';\nimport { TransferFormat, LogLevel } from '../constants.js';\nimport type { ITransport, ILogger } from '../interfaces.js';\nimport type { Readable } from 'node:stream';\n\n/** How long a single poll GET can hang before we issue a new one. */\nconst POLL_TIMEOUT_MS = 100_000;\n\nexport class LongPollingTransport implements ITransport {\n readonly name = 'LongPolling' as const;\n\n readonly #httpClient: IHttpClient;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #logger: ILogger;\n readonly #extraHeaders: Record<string, string>;\n\n #url: string | null = null;\n #running: boolean = false;\n #pollImmediate: ReturnType<typeof setImmediate> | null = null;\n #activeAbort: (() => void) | null = null;\n #transferFormat: TransferFormat = TransferFormat.Text;\n\n onreceive: ((data: string | Uint8Array) => void) | null = null;\n onclose: ((error?: Error) => void) | null = null;\n\n constructor(\n httpClient: IHttpClient,\n accessTokenFactory: (() => Promise<string | null>) | null,\n logger: ILogger,\n extraHeaders: Record<string, string> = {},\n ) {\n this.#httpClient = httpClient;\n this.#accessTokenFactory = accessTokenFactory;\n this.#logger = logger;\n this.#extraHeaders = extraHeaders;\n }\n\n async connect(url: string, transferFormat: TransferFormat): Promise<void> {\n this.#logger.log(LogLevel.Trace, `(LongPolling transport) Connecting to ${url}.`);\n this.#url = url;\n this.#running = true;\n this.#transferFormat = transferFormat;\n\n // Validate the connection with an initial poll\n await this.#poll(url, /* isConnect */ true);\n\n // Start the background poll loop\n this.#schedulePoll();\n this.#logger.log(LogLevel.Information, '(LongPolling transport) Connected.');\n }\n\n async send(data: string | Uint8Array): Promise<void> {\n if (!this.#running || !this.#url) {\n throw new Error('LongPolling transport is not connected.');\n }\n\n const headers = await this.#buildHeaders({\n 'Content-Type': typeof data === 'string'\n ? 'text/plain;charset=UTF-8'\n : 'application/octet-stream',\n });\n\n const result = await this.#httpClient.post(this.#url, { headers, body: data });\n\n if (result.status < 200 || result.status >= 300) {\n throw new Error(`Long polling send failed with status ${result.status}.`);\n }\n }\n\n async stop(): Promise<void> {\n this.#running = false;\n\n if (this.#pollImmediate !== null) {\n clearImmediate(this.#pollImmediate);\n this.#pollImmediate = null;\n }\n\n this.#activeAbort?.();\n this.#activeAbort = null;\n\n if (this.#url) {\n try {\n const headers = await this.#buildHeaders();\n await this.#httpClient.delete(this.#url, { headers });\n } catch (e) {\n this.#logger.log(\n LogLevel.Warning,\n `(LongPolling transport) Error sending DELETE: ${(e as Error).message}`,\n );\n }\n }\n }\n\n // ─── Internal polling ─────────────────────────────────────────────────────\n\n #schedulePoll(): void {\n if (!this.#running) return;\n this.#pollImmediate = setImmediate(() => void this.#pollLoop());\n }\n\n async #pollLoop(): Promise<void> {\n /* istanbul ignore next - #schedulePoll()'s !#running guard and\n clearImmediate() in stop() together prevent #pollLoop from ever\n being called once the transport has stopped; this is a\n belt-and-suspenders defence. */\n if (!this.#running || !this.#url) return;\n try {\n await this.#poll(this.#url, /* isConnect */ false);\n } catch (err) {\n /* istanbul ignore else - between #poll re-throwing and this catch,\n no macrotask can run to set #running=false; the false branch is\n a belt-and-suspenders defence against a theoretical race. */\n if (this.#running) {\n this.#logger.log(\n LogLevel.Error,\n `(LongPolling transport) Poll error: ${(err as Error).message}`,\n );\n this.#running = false;\n this.onclose?.(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n }\n this.#schedulePoll();\n }\n\n async #poll(url: string, isConnect: boolean): Promise<void> {\n const headers = await this.#buildHeaders();\n\n let res;\n try {\n res = await this.#httpClient.stream('GET', url, { headers, timeout: POLL_TIMEOUT_MS });\n this.#activeAbort = res.abort;\n } catch (err) {\n if (!this.#running) return; // normal stop - swallow\n throw err;\n }\n\n if (res.statusCode === 204) {\n // Server ended connection gracefully\n await readAll(res.body);\n this.#activeAbort = null;\n this.#logger.log(LogLevel.Information, '(LongPolling transport) Server closed (204).');\n this.#running = false;\n this.onclose?.();\n return;\n }\n\n if (res.statusCode < 200 || res.statusCode >= 300) {\n await readAll(res.body);\n this.#activeAbort = null;\n const err = new Error(`Long polling received unexpected status ${res.statusCode}.`);\n if (!isConnect) {\n this.#running = false;\n this.onclose?.(err);\n } else {\n throw err;\n }\n return;\n }\n\n let body: Buffer;\n try {\n body = await readAll(res.body);\n } catch (err) {\n /* istanbul ignore next -- only an explicit stop aborts the active body */\n if (!this.#running) return;\n /* istanbul ignore next -- body errors are propagated to the poll loop */\n throw err;\n } finally {\n this.#activeAbort = null;\n }\n if (body.length > 0) {\n const data = this.#transferFormat === TransferFormat.Binary\n ? new Uint8Array(body.buffer, body.byteOffset, body.byteLength)\n : body.toString('utf8');\n this.#logger.log(LogLevel.Trace, `(LongPolling transport) Received ${body.length} bytes.`);\n this.onreceive?.(data);\n }\n }\n\n async #buildHeaders(extra: Record<string, string> = {}): Promise<Record<string, string>> {\n const headers: Record<string, string> = { ...this.#extraHeaders, ...extra };\n if (this.#accessTokenFactory) {\n const token = await this.#accessTokenFactory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n return headers;\n }\n}\n\nfunction readAll(stream: Readable): Promise<Buffer> {\n return new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n stream.on('data', (chunk: Buffer | string) => {\n /* istanbul ignore next -- Node HTTP response streams emit Buffer chunks */\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n });\n stream.on('end', () => resolve(Buffer.concat(chunks)));\n stream.on('error', reject);\n });\n}\n","/**\n * logger.ts\n *\n * Built-in ILogger implementations.\n * ConsoleLogger - writes to console with timestamps and severity labels.\n * NullLogger - discards everything (default when no logger is configured).\n */\n\nimport { LogLevel } from './constants.js';\nimport type { ILogger } from './interfaces.js';\n\n// ─── ConsoleLogger ────────────────────────────────────────────────────────────\n\nexport class ConsoleLogger implements ILogger {\n readonly #minimumLevel: LogLevel;\n\n constructor(minimumLevel: LogLevel = LogLevel.Information) {\n this.#minimumLevel = minimumLevel;\n }\n\n log(level: LogLevel, message: string): void {\n if (level < this.#minimumLevel) return;\n\n const ts = new Date().toISOString();\n const label = logLevelName(level);\n const line = `[${ts}] [${label}] ${message}`;\n\n switch (level) {\n case LogLevel.Trace:\n case LogLevel.Debug:\n console.debug(line);\n break;\n case LogLevel.Warning:\n console.warn(line);\n break;\n case LogLevel.Error:\n case LogLevel.Critical:\n console.error(line);\n break;\n default:\n console.log(line);\n break;\n }\n }\n}\n\n// ─── NullLogger ───────────────────────────────────────────────────────────────\n\nexport class NullLogger implements ILogger {\n /** Singleton - no state, so one instance is enough. */\n static readonly instance: NullLogger = new NullLogger();\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n log(_logLevel: LogLevel, _message: string): void {\n // intentionally empty\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Reverse-map a LogLevel number to its string label. */\nfunction logLevelName(level: LogLevel): string {\n const entry = (Object.entries(LogLevel) as [string, LogLevel][]).find(\n ([, v]) => v === level\n );\n return entry?.[0] ?? String(level);\n}\n\n/** Normalise a LogLevel number or ILogger into an ILogger. */\nexport function resolveLogger(logLevelOrLogger: LogLevel | ILogger): ILogger {\n if (typeof logLevelOrLogger === 'number') {\n return new ConsoleLogger(logLevelOrLogger);\n }\n if (\n logLevelOrLogger != null &&\n typeof logLevelOrLogger === 'object' &&\n typeof (logLevelOrLogger as ILogger).log === 'function'\n ) {\n return logLevelOrLogger as ILogger;\n }\n throw new TypeError(\n 'configureLogging expects a LogLevel number or an object with a log(level, message) method.'\n );\n}\n","/**\n * errors.ts\n *\n * Typed error classes for the SignalR client. Each has a distinct `name`\n * so callers can use `instanceof` or switch on `error.name` to distinguish\n * error categories at runtime.\n */\n\n// ─── Base ────────────────────────────────────────────────────────────────────\n\n/** Thrown when a hub method invocation fails with a server-side error. */\nexport class HubError extends Error {\n override readonly name = 'HubError' as const;\n\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an in-flight operation is cancelled (e.g. connection closed). */\nexport class AbortError extends Error {\n override readonly name = 'AbortError' as const;\n\n constructor(message = 'The operation was aborted.') {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown on network-level transport failures. */\nexport class TransportError extends Error {\n override readonly name = 'TransportError' as const;\n readonly statusCode: number | undefined;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.statusCode = statusCode;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when the SignalR protocol handshake is rejected by the server. */\nexport class HandshakeError extends Error {\n override readonly name = 'HandshakeError' as const;\n\n constructor(message: string) {\n super(message);\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when no acceptable transport could be negotiated. */\nexport class UnsupportedTransportError extends Error {\n override readonly name = 'UnsupportedTransportError' as const;\n readonly transport: number | null;\n\n constructor(message: string, transport: number | null) {\n super(message);\n this.transport = transport;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown internally when negotiate returns an Azure SignalR redirect.\n * Handled transparently by HubConnection - not exposed to callers.\n * @internal\n */\nexport class RedirectError extends Error {\n override readonly name = 'RedirectError' as const;\n readonly url: string;\n readonly accessToken: string | undefined;\n\n constructor(url: string, accessToken?: string) {\n super(`Redirected to ${url}`);\n this.url = url;\n this.accessToken = accessToken;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n// ─── Type guard helpers ───────────────────────────────────────────────────────\n\nexport function isHubError(e: unknown): e is HubError {\n return e instanceof HubError;\n}\n\nexport function isAbortError(e: unknown): e is AbortError {\n return e instanceof AbortError;\n}\n\nexport function isTransportError(e: unknown): e is TransportError {\n return e instanceof TransportError;\n}\n","/**\n * hub-connection.ts\n *\n * Core HubConnection - the main object users interact with.\n *\n * Mirrors the Microsoft SignalR JavaScript client API with full TypeScript types:\n * start() / stop()\n * invoke<T>(method, ...args) → Promise<T>\n * send(method, ...args) → Promise<void>\n * stream<T>(method, ...args) → IStreamResult<T>\n * on(method, handler)\n * off(method, [handler])\n * onclose / onreconnecting / onreconnected\n */\n\nimport { DispatchHttpClient } from './http-client.js';\nimport {\n JsonHubProtocol,\n parseHandshakeResponse,\n} from './protocols/json-hub-protocol.js';\nimport { WebSocketTransport } from './transports/websocket-transport.js';\nimport { ServerSentEventsTransport } from './transports/sse-transport.js';\nimport { LongPollingTransport } from './transports/long-polling-transport.js';\nimport { NullLogger } from './logger.js';\nimport {\n MessageType,\n HubConnectionState,\n HttpTransportType,\n TransferFormat,\n LogLevel,\n NEGOTIATE_VERSION,\n DEFAULT_PING_INTERVAL_IN_MS,\n DEFAULT_SERVER_TIMEOUT_IN_MS,\n} from './constants.js';\nimport {\n HubError,\n AbortError,\n TransportError,\n UnsupportedTransportError,\n} from './errors.js';\nimport type {\n ITransport,\n ILogger,\n IHttpClient,\n IRetryPolicy,\n RetryContext,\n IStreamResult,\n IStreamSubscriber,\n ISubscription,\n NegotiateResponse,\n Dispatcher,\n IHubProtocol,\n} from './interfaces.js';\nimport type { HubMessage, InvocationId } from './messages.js';\nimport { toInvocationId } from './messages.js';\n\nconst MAX_REDIRECTS = 100;\n\n// ─── Configuration ────────────────────────────────────────────────────────────\n\nexport interface HubConnectionOptions {\n readonly logger?: ILogger;\n readonly accessTokenFactory?: () => Promise<string | null>;\n /** Bitmask of HttpTransportType flags (default: all transports). */\n readonly transport?: number;\n readonly headers?: Record<string, string>;\n readonly skipNegotiation?: boolean;\n readonly serverTimeoutInMilliseconds?: number;\n readonly keepAliveIntervalInMilliseconds?: number;\n /**\n * Override the SignalR handshake timeout (ms). Defaults to 15 000.\n * Intended for testing; production code should leave this at the default.\n */\n readonly handshakeTimeoutInMilliseconds?: number;\n readonly reconnectPolicy?: IRetryPolicy | null;\n /**\n * undici Dispatcher shared by all HTTP requests (negotiate, SSE, polling)\n * and the WebSocket upgrade for this connection.\n *\n * Pass an `Agent`, `Pool`, `Client`, `ProxyAgent`, etc. to customise\n * connection pooling, TLS, or proxy routing for the entire SignalR session.\n * When omitted, undici's process-global default agent is used.\n */\n readonly dispatcher?: Dispatcher;\n /**\n * Custom HTTP client to use for all requests made by this connection\n * (negotiate, SSE body reads, long-polling).\n *\n * When omitted, a `DispatchHttpClient` is created automatically using\n * the `dispatcher` option (if any). Provide this to use a different\n * undici primitive (e.g. `FetchHttpClient`) or to inject a mock in tests.\n */\n readonly httpClient?: IHttpClient;\n /** Hub wire protocol. Defaults to JSON protocol version 1. */\n readonly protocol?: IHubProtocol;\n /** Maximum accepted transport payload size. Defaults to 32 MiB. */\n readonly maximumReceiveMessageSize?: number;\n /** Internal: close a builder-created dispatcher when the connection ends. */\n readonly ownsDispatcher?: boolean;\n}\n\n// ─── Internal pending-invocation tracking ────────────────────────────────────\n\ninterface PendingInvocation<T = unknown> {\n resolve: (value: T) => void;\n reject: (err: Error) => void;\n}\n\ninterface PendingStream<T = unknown> {\n next: (value: T) => void;\n error: (err: Error) => void;\n complete: () => void;\n}\n\n// ─── Subscription (supports `using` keyword via Symbol.dispose) ───────────────\n\nclass StreamSubscription implements ISubscription {\n #disposed = false;\n readonly #cancel: () => void;\n\n constructor(cancel: () => void) {\n this.#cancel = cancel;\n }\n\n dispose(): void {\n if (!this.#disposed) {\n this.#disposed = true;\n this.#cancel();\n }\n }\n\n /** TS 5.2+ `using` keyword support. */\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\n// ─── HubConnection ────────────────────────────────────────────────────────────\n\nexport class HubConnection {\n readonly #url: string;\n readonly #logger: ILogger;\n readonly #accessTokenFactory: (() => Promise<string | null>) | null;\n readonly #requestedTransport: number;\n readonly #extraHeaders: Record<string, string>;\n readonly #skipNegotiation: boolean;\n readonly #serverTimeout: number;\n readonly #pingInterval: number;\n readonly #handshakeTimeout: number;\n readonly #reconnectPolicy: IRetryPolicy | null;\n\n readonly #protocol: IHubProtocol;\n readonly #http: IHttpClient;\n readonly #dispatcher: Dispatcher | undefined;\n readonly #ownsDispatcher: boolean;\n readonly #maximumReceiveMessageSize: number;\n\n #transport: ITransport | null = null;\n #connectionId: string | null = null;\n #connectionToken: string | null = null;\n #state: HubConnectionState = HubConnectionState.Disconnected;\n #stopping: boolean = false;\n\n /** Pending `invoke()` calls awaiting a Completion message. */\n readonly #callbacks: Map<InvocationId, PendingInvocation> = new Map();\n /** Active server-streaming subscriptions awaiting StreamItem/Completion. */\n readonly #streamCbs: Map<InvocationId, PendingStream> = new Map();\n /** Client-method handlers registered via `on()`. */\n readonly #methods: Map<string, Set<(...args: unknown[]) => unknown>> = new Map();\n\n /** Registered `onclose` callbacks. */\n readonly #closedCallbacks: Array<(error?: Error) => void> = [];\n /** Registered `onreconnecting` callbacks. */\n readonly #reconnectingCallbacks: Array<(error?: Error) => void> = [];\n /** Registered `onreconnected` callbacks. */\n readonly #reconnectedCallbacks: Array<(connectionId: string | null) => void> = [];\n\n #pingTimer: ReturnType<typeof setTimeout> | null = null;\n #serverTimeoutTimer: ReturnType<typeof setTimeout> | null = null;\n #handshakeTimer: ReturnType<typeof setTimeout> | null = null;\n\n #handshakeResolver: (() => void) | null = null;\n #handshakeRejecter: ((e: Error) => void) | null = null;\n\n #handshakeBuffer: Buffer = Buffer.alloc(0);\n #dispatcherClosePromise: Promise<void> | null = null;\n #invocationSeq: number = 0;\n\n constructor(url: string, options: HubConnectionOptions = {}) {\n this.#url = url;\n this.#logger = options.logger ?? NullLogger.instance;\n this.#accessTokenFactory = options.accessTokenFactory ?? null;\n this.#requestedTransport = options.transport\n ?? (HttpTransportType.WebSockets | HttpTransportType.ServerSentEvents | HttpTransportType.LongPolling);\n this.#extraHeaders = options.headers ?? {};\n this.#skipNegotiation = options.skipNegotiation ?? false;\n this.#serverTimeout = options.serverTimeoutInMilliseconds ?? DEFAULT_SERVER_TIMEOUT_IN_MS;\n this.#pingInterval = options.keepAliveIntervalInMilliseconds ?? DEFAULT_PING_INTERVAL_IN_MS;\n this.#handshakeTimeout = options.handshakeTimeoutInMilliseconds ?? 15_000;\n this.#reconnectPolicy = options.reconnectPolicy ?? null;\n this.#protocol = options.protocol ?? new JsonHubProtocol();\n this.#dispatcher = options.dispatcher;\n this.#ownsDispatcher = options.ownsDispatcher ?? false;\n this.#maximumReceiveMessageSize = options.maximumReceiveMessageSize ?? 32 * 1024 * 1024;\n // Use the caller-supplied client, or create a DispatchHttpClient that shares\n // the same dispatcher so negotiate + polls + WebSocket all use one pool.\n this.#http = options.httpClient\n ?? new DispatchHttpClient({\n headers: this.#extraHeaders,\n ...(options.dispatcher !== undefined && { dispatcher: options.dispatcher }),\n });\n }\n\n // ─── State ───────────────────────────────────────────────────────────────\n\n get state(): HubConnectionState { return this.#state; }\n get connectionId(): string | null { return this.#connectionId; }\n\n // ─── Lifecycle ───────────────────────────────────────────────────────────\n\n async start(): Promise<void> {\n if (this.#state !== HubConnectionState.Disconnected) {\n throw new Error(\n `Cannot start: connection is not Disconnected (current: ${this.#state}).`\n );\n }\n this.#state = HubConnectionState.Connecting;\n this.#stopping = false;\n this.#logger.log(LogLevel.Debug, 'Starting HubConnection.');\n\n try {\n await this.#startInternal();\n this.#state = HubConnectionState.Connected;\n this.#logger.log(LogLevel.Information, 'HubConnection connected.');\n } catch (err) {\n this.#clearTimers();\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n this.#handshakeBuffer = Buffer.alloc(0);\n if (this.#transport) {\n this.#transport.onclose = null;\n await this.#transport.stop().catch(/* istanbul ignore next -- cleanup is best-effort */ () => {});\n this.#transport = null;\n }\n this.#state = HubConnectionState.Disconnected;\n this.#logger.log(LogLevel.Error, `Failed to start: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async stop(): Promise<void> {\n if (this.#state === HubConnectionState.Disconnected) return;\n this.#stopping = true;\n this.#state = HubConnectionState.Disconnecting;\n this.#logger.log(LogLevel.Debug, 'Stopping HubConnection.');\n this.#clearTimers();\n\n const stopErr = new AbortError('Connection stopped before the invocation completed.');\n this.#rejectAllPending(stopErr);\n\n /* istanbul ignore else -- non-disconnected connections normally own a transport */\n if (this.#transport) {\n this.#transport.onclose = null;\n try { await this.#transport.stop(); } catch { /* ignore */ }\n this.#transport = null;\n }\n this.#completeClose();\n await this.#closeOwnedDispatcher();\n this.#logger.log(LogLevel.Information, 'HubConnection stopped.');\n }\n\n // ─── Sending ─────────────────────────────────────────────────────────────\n\n /**\n * Invoke a hub method and return the server's result.\n *\n * @typeParam T The expected return type. Asserted at runtime - the server\n * decides the actual value.\n */\n invoke<T = void>(methodName: string, ...args: unknown[]): Promise<T> {\n this.#assertConnected('invoke');\n const id = this.#nextId();\n const msg = this.#encode(JsonHubProtocol.invocation(id, methodName, args));\n\n return new Promise<T>((resolve, reject) => {\n this.#callbacks.set(id, {\n resolve: resolve as (v: unknown) => void,\n reject,\n });\n this.#send(msg).catch((err: Error) => {\n this.#callbacks.delete(id);\n reject(err);\n });\n });\n }\n\n /**\n * Fire-and-forget hub method invocation.\n * The server does not send a completion message.\n */\n send(methodName: string, ...args: unknown[]): Promise<void> {\n this.#assertConnected('send');\n const msg = this.#encode(JsonHubProtocol.send(methodName, args));\n return this.#send(msg);\n }\n\n // ─── Server-streaming ────────────────────────────────────────────────────\n\n /**\n * Start a server-streaming invocation immediately.\n * The returned `ISubscription` implements `Symbol.dispose` for `using`.\n *\n * @typeParam T Type of each streamed item.\n *\n * @example\n * ```ts\n * using sub = connection.stream<number>('Counter', 10).subscribe({\n * next: (n) => console.log(n),\n * complete: () => console.log('done'),\n * });\n * ```\n */\n stream<T = unknown>(methodName: string, ...args: unknown[]): IStreamResult<T> {\n this.#assertConnected('stream');\n const id = this.#nextId();\n type Notification =\n | { kind: 'next'; value: T }\n | { kind: 'error'; error: Error }\n | { kind: 'complete' };\n const queued: Notification[] = [];\n let activeSubscriber: IStreamSubscriber<T> | null = null;\n let subscribed = false;\n\n const deliver = (notification: Notification): void => {\n if (!activeSubscriber) {\n queued.push(notification);\n return;\n }\n if (notification.kind === 'next') activeSubscriber.next?.(notification.value);\n else if (notification.kind === 'error') activeSubscriber.error?.(notification.error);\n else activeSubscriber.complete?.();\n };\n\n this.#streamCbs.set(id, {\n next: (value) => deliver({ kind: 'next', value: value as T }),\n error: (error) => deliver({ kind: 'error', error }),\n complete: () => deliver({ kind: 'complete' }),\n });\n\n const msg = this.#encode(JsonHubProtocol.streamInvocation(id, methodName, args));\n this.#send(msg).catch((error: Error) => {\n this.#streamCbs.delete(id);\n deliver({ kind: 'error', error });\n });\n\n return {\n subscribe: (subscriber: IStreamSubscriber<T>): ISubscription => {\n if (subscribed) throw new Error('A stream result can only be subscribed to once.');\n subscribed = true;\n activeSubscriber = subscriber;\n for (const notification of queued.splice(0)) deliver(notification);\n\n return new StreamSubscription(() => {\n if (this.#streamCbs.has(id)) {\n this.#streamCbs.delete(id);\n this.#send(\n this.#encode(JsonHubProtocol.cancelInvocation(id))\n ).catch(\n /* istanbul ignore next -- cancellation is intentionally best-effort */\n () => { /* best-effort */ },\n );\n }\n });\n },\n };\n }\n\n // ─── Event registration ───────────────────────────────────────────────────\n\n /**\n * Register a handler for a server→client hub method.\n * Multiple handlers for the same method are supported.\n *\n * @typeParam TArgs Tuple of argument types for the hub method.\n */\n on<TArgs extends unknown[] = unknown[]>(\n methodName: string,\n handler: (...args: TArgs) => unknown,\n ): void {\n const key = methodName.toLowerCase();\n if (!this.#methods.has(key)) this.#methods.set(key, new Set());\n this.#methods.get(key)!.add(handler as (...args: unknown[]) => unknown);\n }\n\n /**\n * Remove a previously registered handler, or all handlers for a method.\n */\n off(methodName: string, handler?: (...args: unknown[]) => unknown): void {\n const key = methodName.toLowerCase();\n if (!this.#methods.has(key)) return;\n if (handler == null) {\n this.#methods.delete(key);\n } else {\n this.#methods.get(key)!.delete(handler);\n if (this.#methods.get(key)!.size === 0) this.#methods.delete(key);\n }\n }\n\n onclose(callback: (error?: Error) => void): void { this.#closedCallbacks.push(callback); }\n onreconnecting(callback:(error?: Error) => void): void { this.#reconnectingCallbacks.push(callback); }\n onreconnected(callback: (connectionId: string | null) => void): void { this.#reconnectedCallbacks.push(callback); }\n\n // ─── Internal: start sequence ────────────────────────────────────────────\n\n async #startInternal(): Promise<void> {\n let url = this.#url;\n\n if (this.#skipNegotiation) {\n if (this.#requestedTransport !== HttpTransportType.WebSockets) {\n throw new Error('skipNegotiation requires WebSockets as the only transport.');\n }\n this.#transport = this.#createTransport(HttpTransportType.WebSockets);\n await this.#connectTransport(url, this.#protocol.transferFormat);\n } else {\n let redirectCount = 0;\n for (;;) {\n const neg = await this.#negotiate(url);\n\n if (neg.url) {\n if (redirectCount++ >= MAX_REDIRECTS) throw new Error('Too many negotiate redirects.');\n url = neg.url;\n if (neg.accessToken) {\n const staticToken = neg.accessToken;\n this.#overrideAccessToken(() => Promise.resolve(staticToken));\n }\n continue;\n }\n\n /* istanbul ignore next -- a successful negotiate response must include connectionId */\n this.#connectionId = neg.connectionId ?? null;\n /* istanbul ignore next -- the protocol requires a token or connectionId */\n this.#connectionToken = neg.connectionToken ?? neg.connectionId ?? null;\n\n /* istanbul ignore next -- the protocol requires availableTransports */\n await this.#selectTransport(url, neg.availableTransports ?? []);\n break;\n }\n }\n\n // Wire message routing\n this.#transport!.onreceive = (data) => this.#processIncoming(data);\n this.#transport!.onclose = (err) => this.#onTransportClosed(err);\n\n // Protocol handshake\n await this.#performHandshake();\n\n // Keep-alive\n this.#resetPingTimer();\n this.#resetServerTimeoutTimer();\n }\n\n // Rebinds the access token factory (used after Azure SignalR redirect).\n // Stored as a field to allow rebinding without recreating the instance.\n #_accessTokenFactory: (() => Promise<string | null>) | null = null;\n\n #overrideAccessToken(factory: () => Promise<string | null>): void {\n this.#_accessTokenFactory = factory;\n }\n\n #getAccessTokenFactory(): (() => Promise<string | null>) | null {\n return this.#_accessTokenFactory ?? this.#accessTokenFactory;\n }\n\n async #negotiate(baseUrl: string): Promise<NegotiateResponse> {\n // Use the URL API so that an existing query string in baseUrl (e.g.\n // \"?token=abc\") does not corrupt the pathname. Simple string concatenation\n // would produce \"?token=abc/negotiate\" - wrong path, wrong query string.\n const negotiateUrl = new URL(baseUrl);\n negotiateUrl.pathname = negotiateUrl.pathname.replace(/\\/$/, '') + '/negotiate';\n negotiateUrl.searchParams.set('negotiateVersion', String(NEGOTIATE_VERSION));\n const url = negotiateUrl.toString();\n this.#logger.log(LogLevel.Debug, `Sending negotiate request to ${url}.`);\n\n const headers: Record<string, string> = { ...this.#extraHeaders };\n const factory = this.#getAccessTokenFactory();\n if (factory) {\n const token = await factory();\n if (token) headers['Authorization'] = `Bearer ${token}`;\n }\n\n const res = await this.#http.post(url, { headers });\n\n if (res.status !== 200) {\n throw new TransportError(\n `Unexpected status code ${res.status} from negotiate.`,\n res.status\n );\n }\n\n if (Buffer.byteLength(res.body, 'utf8') > this.#maximumReceiveMessageSize) {\n throw new Error(`Negotiate response exceeds ${this.#maximumReceiveMessageSize} bytes.`);\n }\n\n const body = JSON.parse(res.body) as NegotiateResponse;\n if (body.error) throw new Error(`Negotiate returned error: ${body.error}`);\n return body;\n }\n\n async #selectTransport(\n url: string,\n available: readonly { transport: string; transferFormats: readonly string[] }[],\n ): Promise<void> {\n const ORDERED = [\n { flag: HttpTransportType.WebSockets, name: 'WebSockets' },\n { flag: HttpTransportType.ServerSentEvents, name: 'ServerSentEvents' },\n { flag: HttpTransportType.LongPolling, name: 'LongPolling' },\n ] as const;\n /* istanbul ignore next -- both protocol formats are exercised at the protocol boundary */\n const formatName = this.#protocol.transferFormat === TransferFormat.Binary ? 'Binary' : 'Text';\n\n for (const pref of ORDERED) {\n if ((this.#requestedTransport & pref.flag) === 0) continue;\n const offered = available.find((candidate) => candidate.transport === pref.name);\n if (!offered?.transferFormats.includes(formatName)) continue;\n\n this.#logger.log(LogLevel.Debug, `Trying ${pref.name} transport.`);\n const transport = this.#createTransport(pref.flag);\n /* istanbul ignore next -- successful negotiation always supplies a token */\n const token = this.#connectionToken ?? '';\n const tUrl = appendParam(url, 'id', token);\n\n try {\n await transport.connect(tUrl, this.#protocol.transferFormat);\n this.#transport = transport;\n return;\n } catch (err) {\n this.#logger.log(LogLevel.Warning, `${pref.name} failed: ${(err as Error).message}`);\n }\n }\n\n throw new UnsupportedTransportError(\n 'Unable to connect with any of the available transports.',\n null\n );\n }\n\n async #connectTransport(url: string, format: TransferFormat): Promise<void> {\n await this.#transport!.connect(url, format);\n }\n\n #createTransport(type: number): ITransport {\n const factory = this.#getAccessTokenFactory();\n const headers = this.#extraHeaders;\n switch (type) {\n case HttpTransportType.WebSockets:\n return new WebSocketTransport(factory, this.#logger, headers, this.#dispatcher);\n case HttpTransportType.ServerSentEvents:\n return new ServerSentEventsTransport(this.#http, factory, this.#logger, headers);\n case HttpTransportType.LongPolling:\n return new LongPollingTransport(this.#http, factory, this.#logger, headers);\n /* istanbul ignore next */\n default:\n throw new UnsupportedTransportError(`Unknown transport type: ${type}`, type);\n }\n }\n\n // ─── Internal: handshake ─────────────────────────────────────────────────\n\n #performHandshake(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.#handshakeResolver = resolve;\n this.#handshakeRejecter = reject;\n\n const request = JSON.stringify({ protocol: this.#protocol.name, version: this.#protocol.version }) + '\\x1e';\n const fail = (error: unknown): void => {\n clearTimeout(this.#handshakeTimer!);\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n /* istanbul ignore next -- transport.send rejects with Error */\n reject(error instanceof Error ? error : new Error(String(error)));\n };\n this.#transport!.send(request).catch(fail);\n\n this.#handshakeTimer = setTimeout(() => {\n fail(new Error('Server timeout: no handshake response received.'));\n }, this.#handshakeTimeout);\n });\n }\n\n // ─── Internal: incoming data ─────────────────────────────────────────────\n\n #processIncoming(data: string | Uint8Array): void {\n this.#resetServerTimeoutTimer();\n /* istanbul ignore next -- binary input is exercised through binary protocol tests */\n const bytes = typeof data === 'string' ? Buffer.from(data, 'utf8') : Buffer.from(data);\n if (bytes.byteLength > this.#maximumReceiveMessageSize) {\n this.#stopWithError(new Error(`Incoming message exceeds ${this.#maximumReceiveMessageSize} bytes.`));\n return;\n }\n\n // During handshake the first data is the response\n if (this.#handshakeResolver) {\n this.#handshakeBuffer = Buffer.concat([this.#handshakeBuffer, bytes]);\n const separator = this.#handshakeBuffer.indexOf(0x1e);\n /* istanbul ignore next -- partial handshakes are buffered for the next frame */\n if (separator === -1) return;\n try {\n parseHandshakeResponse(this.#handshakeBuffer.subarray(0, separator + 1).toString('utf8'));\n const remainder = this.#handshakeBuffer.subarray(separator + 1);\n this.#handshakeBuffer = Buffer.alloc(0);\n this.#logger.log(LogLevel.Debug, 'Handshake complete.');\n clearTimeout(this.#handshakeTimer!);\n const r = this.#handshakeResolver;\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n r();\n /* istanbul ignore next -- servers ordinarily send handshake and hub frames separately */\n if (remainder.length > 0) this.#processProtocolPayload(remainder);\n } catch (err) {\n clearTimeout(this.#handshakeTimer!);\n const r = this.#handshakeRejecter!;\n this.#handshakeResolver = null;\n this.#handshakeRejecter = null;\n /* istanbul ignore next -- JSON.parse and protocol validation throw Error objects */\n r(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n return;\n }\n\n this.#processProtocolPayload(bytes);\n }\n\n #processProtocolPayload(bytes: Uint8Array): void {\n /* istanbul ignore next -- transports do not emit empty payloads */\n if (bytes.length === 0) return;\n\n let messages;\n try {\n /* istanbul ignore next -- MessagePack parsing is covered directly */\n const input = this.#protocol.transferFormat === TransferFormat.Text\n ? Buffer.from(bytes).toString('utf8')\n : Uint8Array.from(bytes).buffer;\n messages = this.#protocol.parseMessages(input, this.#logger);\n } catch (err) {\n this.#logger.log(LogLevel.Error, `Error parsing messages: ${(err as Error).message}`);\n /* istanbul ignore next -- protocol parsers throw Error objects */\n this.#stopWithError(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n\n for (const msg of messages) {\n switch (msg.type) {\n // ── Type 1: Server calls a client method ──────────────────────────\n case MessageType.Invocation: {\n void this.#invokeClientMethod(msg);\n break;\n }\n\n // ── Type 2: One item from a server stream ─────────────────────────\n // Per spec, StreamItem carries only `item`; there is no `error` field.\n case MessageType.StreamItem: {\n const sc = this.#streamCbs.get(msg.invocationId);\n if (!sc) break;\n sc.next(msg.item);\n break;\n }\n\n // ── Type 3: Completion of an invoke() or stream ───────────────────\n case MessageType.Completion: {\n const cb = this.#callbacks.get(msg.invocationId);\n if (cb) {\n this.#callbacks.delete(msg.invocationId);\n if (msg.error) cb.reject(new HubError(msg.error));\n else cb.resolve(msg.result ?? null);\n }\n const sc = this.#streamCbs.get(msg.invocationId);\n if (sc) {\n this.#streamCbs.delete(msg.invocationId);\n if (msg.error) sc.error(new HubError(msg.error));\n else sc.complete();\n }\n break;\n }\n\n // ── Type 6: Ping ──────────────────────────────────────────────────\n case MessageType.Ping:\n // Server-timeout watchdog already reset at the top of this method\n break;\n\n // ── Type 7: Server-initiated close ────────────────────────────────\n case MessageType.Close: {\n this.#logger.log(LogLevel.Information, 'Server sent Close message.');\n const closeErr = msg.error ? new HubError(msg.error) : null;\n // Per spec: if allowReconnect is true AND the client has a reconnect\n // policy, the client should attempt reconnection rather than a\n // permanent disconnect. Null out onclose on the old transport to\n // prevent #onTransportClosed from firing a second reconnect loop.\n if (msg.allowReconnect && this.#reconnectPolicy && !this.#stopping) {\n this.#clearTimers();\n /* istanbul ignore next - #transport is always non-null here; null\n is a defensive guard against theoretical concurrent nulling. */\n if (this.#transport) this.#transport.onclose = null;\n const t = this.#transport;\n this.#transport = null;\n this.#rejectAllPending(closeErr ?? new AbortError('Connection closed while reconnecting.'));\n void t?.stop().catch(\n /* istanbul ignore next -- shutdown after a server Close is best-effort */\n () => {},\n );\n void this.#doReconnect(closeErr);\n } else {\n this.#stopWithError(closeErr);\n }\n break;\n }\n\n default:\n this.#logger.log(LogLevel.Warning, `Unknown message type: ${(msg as { type: number }).type}`);\n break;\n }\n }\n }\n\n async #invokeClientMethod(msg: Extract<HubMessage, { type: 1 }>): Promise<void> {\n const handlers = this.#methods.get(msg.target.toLowerCase());\n if (!handlers || handlers.size === 0) {\n this.#logger.log(LogLevel.Warning, `No handler for \"${msg.target}\".`);\n if (msg.invocationId) {\n await this.#send(this.#encode(JsonHubProtocol.completion(\n msg.invocationId, undefined, `No client handler registered for '${msg.target}'.`,\n ))).catch(/* istanbul ignore next -- completion replies are best-effort */ () => {});\n }\n return;\n }\n\n let result: unknown;\n let invocationError: Error | null = null;\n for (const handler of [...handlers]) {\n try {\n result = await handler(...(msg.arguments as unknown[]));\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n invocationError ??= err;\n this.#logger.log(LogLevel.Error, `Handler for \"${msg.target}\" threw: ${err.message}`);\n }\n }\n if (msg.invocationId) {\n const completion: HubMessage = invocationError\n ? { type: MessageType.Completion, invocationId: msg.invocationId, error: invocationError.message }\n : {\n type: MessageType.Completion,\n invocationId: msg.invocationId,\n ...(result !== undefined && { result }),\n };\n await this.#send(this.#encode(completion)).catch(/* istanbul ignore next -- completion replies are best-effort */ () => {});\n }\n }\n\n // ─── Internal: transport closed ──────────────────────────────────────────\n\n #onTransportClosed(err?: Error): void {\n /* istanbul ignore next - WebSocketTransport.stop() nulls #ws before\n calling ws.close(), so the close handler never invokes onclose once\n stop() has set #stopping; this guard is a belt-and-suspenders defence. */\n if (this.#stopping) return;\n this.#logger.log(\n LogLevel.Warning,\n err ? `Transport closed with error: ${err.message}` : 'Transport closed.'\n );\n this.#clearTimers();\n this.#rejectAllPending(err ?? new AbortError('Connection closed while reconnecting.'));\n\n if (this.#reconnectPolicy) {\n void this.#doReconnect(err ?? null);\n } else {\n this.#completeClose(err);\n }\n }\n\n #stopWithError(err: Error | null): void {\n this.#clearTimers();\n void this.#transport?.stop().catch(\n /* istanbul ignore next -- error shutdown is best-effort */\n () => { /* ignore */ },\n );\n this.#transport = null;\n this.#completeClose(err ?? undefined);\n }\n\n #completeClose(err?: Error): void {\n const closeErr = err ?? new AbortError('Connection closed.');\n this.#rejectAllPending(closeErr);\n this.#state = HubConnectionState.Disconnected;\n for (const cb of this.#closedCallbacks) {\n try { cb(err); } catch { /* ignore */ }\n }\n void this.#closeOwnedDispatcher();\n }\n\n #rejectAllPending(err: Error): void {\n this.#callbacks.forEach((cb) => cb.reject(err));\n this.#callbacks.clear();\n this.#streamCbs.forEach((sc) => sc.error(err));\n this.#streamCbs.clear();\n }\n\n // ─── Internal: auto-reconnect ─────────────────────────────────────────────\n\n async #doReconnect(disconnectError: Error | null): Promise<void> {\n this.#state = HubConnectionState.Reconnecting;\n for (const cb of this.#reconnectingCallbacks) {\n try { cb(disconnectError ?? undefined); } catch { /* ignore */ }\n }\n\n let retryCount = 0;\n const startTime = Date.now();\n let lastError = disconnectError;\n\n while (!this.#stopping) {\n const ctx: RetryContext = {\n previousRetryCount: retryCount,\n elapsedMilliseconds: Date.now() - startTime,\n retryReason: lastError,\n };\n const delay = this.#reconnectPolicy!.nextRetryDelayInMilliseconds(ctx);\n if (delay === null) {\n this.#logger.log(LogLevel.Debug, 'Reconnect policy returned null - giving up.');\n break;\n }\n\n this.#logger.log(LogLevel.Information, `Reconnecting in ${delay} ms (attempt ${retryCount + 1}).`);\n await sleep(delay);\n if (this.#stopping) break;\n\n try {\n await this.#startInternal();\n this.#state = HubConnectionState.Connected;\n this.#logger.log(LogLevel.Information, 'Reconnected successfully.');\n for (const cb of this.#reconnectedCallbacks) {\n try { cb(this.#connectionId); } catch { /* ignore */ }\n }\n return;\n } catch (err) {\n retryCount++;\n /* istanbul ignore next - #startInternal() only throws Error instances. */\n lastError = err instanceof Error ? err : new Error(String(err));\n this.#logger.log(LogLevel.Warning, `Reconnect attempt ${retryCount} failed: ${lastError.message}`);\n }\n }\n\n this.#completeClose(lastError ?? undefined);\n }\n\n // ─── Internal: timers ────────────────────────────────────────────────────\n\n #resetPingTimer(): void {\n clearTimeout(this.#pingTimer!);\n this.#pingTimer = setTimeout(async () => {\n /* istanbul ignore next - #clearTimers() always cancels this before state\n leaves Connected; the guard is a defensive fallback. */\n if (this.#state !== HubConnectionState.Connected) return;\n try {\n await this.#send(this.#encode(JsonHubProtocol.ping()));\n } catch (err) {\n this.#logger.log(LogLevel.Warning, `Ping failed: ${(err as Error).message}`);\n }\n this.#resetPingTimer();\n }, this.#pingInterval);\n }\n\n #resetServerTimeoutTimer(): void {\n clearTimeout(this.#serverTimeoutTimer!);\n this.#serverTimeoutTimer = setTimeout(() => {\n this.#logger.log(LogLevel.Warning, 'Server timeout - closing connection.');\n this.#stopWithError(new AbortError('Server timeout: no message received within the timeout period.'));\n }, this.#serverTimeout);\n }\n\n #clearTimers(): void {\n clearTimeout(this.#pingTimer!);\n clearTimeout(this.#serverTimeoutTimer!);\n clearTimeout(this.#handshakeTimer!);\n this.#pingTimer = null;\n this.#serverTimeoutTimer = null;\n this.#handshakeTimer = null;\n }\n\n // ─── Internal: helpers ────────────────────────────────────────────────────\n\n #send(message: string | Uint8Array): Promise<void> {\n this.#resetPingTimer();\n return this.#transport!.send(message);\n }\n\n #encode(message: HubMessage): string | Uint8Array {\n const encoded = this.#protocol.writeMessage(message);\n return typeof encoded === 'string' ? encoded : new Uint8Array(encoded);\n }\n\n #assertConnected(method: string): void {\n if (this.#state !== HubConnectionState.Connected) {\n throw new Error(\n `Cannot call \"${method}\" when connection is not Connected (current: ${this.#state}).`\n );\n }\n }\n\n #nextId(): InvocationId {\n return toInvocationId(String(++this.#invocationSeq));\n }\n\n async #closeOwnedDispatcher(): Promise<void> {\n if (!this.#ownsDispatcher || !this.#dispatcher) return;\n this.#dispatcherClosePromise ??= this.#dispatcher.close().catch(\n /* istanbul ignore next -- shutdown cleanup is best-effort */ () => {},\n );\n await this.#dispatcherClosePromise;\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\n/**\n * Append a single query-string name/value pair to a URL.\n *\n * Uses the WHATWG `URL` API so the operation is always correct regardless of\n * whether the URL already contains a query string, path segments, or both.\n * This avoids the classic bug where naive string concatenation appends a path\n * segment *after* an existing query string, corrupting the URL.\n *\n * e.g. appendParam('https://host/hub?token=x', 'id', 'y')\n * → 'https://host/hub?token=x&id=y' ✓ (not '?token=x&id=y' appended raw)\n */\nfunction appendParam(url: string, name: string, value: string): string {\n const u = new URL(url);\n u.searchParams.append(name, value);\n return u.toString();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise<void>((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * hub-connection-builder.ts\n *\n * Fluent builder for HubConnection - mirrors the official Microsoft client API.\n * Uses `const` type parameters (TS 5.0+) and `NoInfer<T>` (TS 5.4+) where\n * applicable to preserve literal types and prevent unintended widening.\n *\n * Usage\n * ─────\n * const connection = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub', {\n * accessTokenFactory: () => fetchToken(),\n * transport: HttpTransportType.WebSockets,\n * })\n * .configureLogging(LogLevel.Information)\n * .withAutomaticReconnect()\n * .build();\n */\n\nimport { HubConnection } from './hub-connection.js';\nimport type { HubConnectionOptions } from './hub-connection.js';\nimport { resolveLogger } from './logger.js';\nimport { LogLevel, HttpTransportType } from './constants.js';\nimport type { ILogger, IHttpClient, IHubProtocol, IRetryPolicy, RetryContext, Dispatcher } from './interfaces.js';\nimport { CookieAgent } from '@exhumer/undici-cookie-agent';\nimport { CookieJar } from 'tough-cookie';\n\n/** Default reconnect delay sequence in ms: 0, 2 s, 10 s, 30 s then give up. */\nconst DEFAULT_RETRY_DELAYS = [0, 2_000, 10_000, 30_000] as const satisfies readonly number[];\n\n// ─── withUrl option bag ───────────────────────────────────────────────────────\n\nexport interface UrlOptions {\n /** Async function returning a Bearer token (or null for unauthenticated). */\n readonly accessTokenFactory?: () => Promise<string | null>;\n /**\n * Bitmask of {@link HttpTransportType} values.\n * Defaults to all three transports if omitted.\n */\n readonly transport?: number;\n /** Extra HTTP headers appended to every request (negotiate, upgrade, poll…). */\n readonly headers?: Record<string, string>;\n /**\n * Skip the /negotiate step and connect directly via WebSocket.\n * Only valid when transport is exclusively `HttpTransportType.WebSockets`.\n */\n readonly skipNegotiation?: boolean;\n /** ms before the connection is considered unresponsive (default: 30 000). */\n readonly serverTimeoutInMilliseconds?: number;\n /** ms between keep-alive pings (default: 15 000). */\n readonly keepAliveIntervalInMilliseconds?: number;\n /** ms to wait for the SignalR handshake response (default: 15 000). */\n readonly handshakeTimeoutInMilliseconds?: number;\n /** Maximum accepted transport payload size (default: 32 MiB). */\n readonly maximumReceiveMessageSize?: number;\n}\n\n// ─── HubConnectionBuilder ────────────────────────────────────────────────────\n\nexport class HubConnectionBuilder {\n #url: string | null = null;\n #urlOptions: UrlOptions = {};\n #logger: ILogger | null = null;\n #reconnectPolicy: IRetryPolicy | null = null;\n #dispatcher: Dispatcher | null = null;\n #httpClient: IHttpClient | null = null;\n #cookieJar: CookieJar | null = null;\n #protocol: IHubProtocol | null = null;\n\n // ─── withUrl ─────────────────────────────────────────────────────────────\n\n withUrl(url: string, options?: UrlOptions): this {\n if (!url || typeof url !== 'string') {\n throw new TypeError('withUrl requires a non-empty string URL.');\n }\n this.#url = url;\n this.#urlOptions = options ?? {};\n return this;\n }\n\n // ─── withCookies ─────────────────────────────────────────────────────────\n\n /**\n * Enable automatic cookie handling for the entire connection session using\n * a `tough-cookie` `CookieJar` and an `@exhumer/undici-cookie-agent` `CookieAgent`.\n *\n * When enabled, the `CookieAgent` wraps every outgoing request - including\n * the `/negotiate` POST, WebSocket upgrade, SSE long-lived GET, and all\n * long-polling requests - so that:\n *\n * 1. `Set-Cookie` headers in the **negotiate response** (and any subsequent\n * response) are stored in the jar automatically.\n * 2. All subsequent requests from the same session include the matching\n * `Cookie` header, exactly as a browser would.\n *\n * @param jar\n * An existing `CookieJar` to use. Pass your own jar when you need to\n * pre-seed cookies (e.g. an auth session cookie obtained before calling\n * `start()`) or inspect the jar after the session ends.\n * When omitted a new, empty jar is created automatically.\n *\n * @throws if {@link withDispatcher} has already been called. To combine a\n * custom dispatcher (e.g. `ProxyAgent`) with cookie support, compose the\n * `cookie` interceptor onto your dispatcher and pass it to `withDispatcher()`:\n *\n * ```ts\n * import { ProxyAgent } from 'undici';\n * import { cookie, CookieJar } from '@exhumer/signalr-client';\n *\n * const jar = new CookieJar();\n * const agent = new ProxyAgent('http://proxy:8080').compose(cookie({ jar }));\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withDispatcher(agent)\n * .build();\n * ```\n *\n * @example\n * ```ts\n * // Automatic jar - no pre-configuration needed\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withCookies()\n * .build();\n *\n * // Pre-seeded jar - inject a session cookie before connecting\n * import { CookieJar } from '@exhumer/signalr-client';\n * const jar = new CookieJar();\n * await jar.setCookie('session=abc123', 'https://example.com');\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withCookies(jar)\n * .build();\n * ```\n */\n withCookies(jar?: CookieJar): this {\n if (this.#dispatcher !== null) {\n throw new Error(\n 'withCookies() cannot be used after withDispatcher(). ' +\n 'To combine a custom dispatcher with cookie support, compose the ' +\n 'cookie interceptor from @exhumer/undici-cookie-agent onto your ' +\n 'dispatcher and pass it to withDispatcher() instead.',\n );\n }\n this.#cookieJar = jar ?? new CookieJar();\n return this;\n }\n\n // ─── withDispatcher ──────────────────────────────────────────────────────\n\n /**\n * Set the undici `Dispatcher` for the entire connection session.\n *\n * The same dispatcher is used for:\n * • the `/negotiate` HTTP POST\n * • the WebSocket upgrade request\n * • SSE long-lived GET and send POSTs\n * • long-polling GETs, POSTs, and DELETE\n *\n * Accepts any `Dispatcher` subclass: `Agent`, `Pool`, `Client`,\n * `ProxyAgent`, `MockAgent`, etc.\n *\n * To combine a custom dispatcher with automatic cookie handling, use\n * `createCookieAgentClass()` to build a cookie-aware variant of your\n * dispatcher and pass that here. Do **not** chain both\n * `withDispatcher()` and `withCookies()` - they are mutually exclusive\n * because `withCookies()` creates its own dispatcher internally.\n *\n * @example\n * ```ts\n * import { ProxyAgent } from 'undici';\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withDispatcher(new ProxyAgent('http://proxy:8080'))\n * .build();\n * ```\n */\n withDispatcher(dispatcher: Dispatcher): this {\n if (this.#cookieJar !== null) {\n throw new Error(\n 'withDispatcher() cannot be used after withCookies(). ' +\n 'To combine a custom dispatcher with cookie support, compose the ' +\n 'cookie interceptor from @exhumer/undici-cookie-agent onto your ' +\n 'dispatcher and pass it to withDispatcher() instead.',\n );\n }\n this.#dispatcher = dispatcher;\n return this;\n }\n\n /**\n * Provide a custom HTTP client implementation.\n *\n * By default `HubConnection` uses `DispatchHttpClient` (undici `dispatch`).\n * Use this to substitute any of the other undici-backed clients, or\n * to inject a mock for testing.\n *\n * @example\n * ```ts\n * import { FetchHttpClient } from '@signalr/client';\n *\n * const conn = new HubConnectionBuilder()\n * .withUrl('https://example.com/hub')\n * .withHttpClient(new FetchHttpClient())\n * .build();\n * ```\n */\n withHttpClient(httpClient: IHttpClient): this {\n this.#httpClient = httpClient;\n return this;\n }\n\n /** Select the hub wire protocol (for example, MessagePack). */\n withHubProtocol(protocol: IHubProtocol): this {\n this.#protocol = protocol;\n return this;\n }\n\n // ─── configureLogging ────────────────────────────────────────────────────\n\n /**\n * Set the minimum log level or provide a custom logger.\n *\n * @param logLevelOrLogger\n * - `LogLevel` number → uses the built-in ConsoleLogger\n * - `ILogger` object → used as-is\n */\n configureLogging(logLevelOrLogger: LogLevel | ILogger): this {\n this.#logger = resolveLogger(logLevelOrLogger);\n return this;\n }\n\n // ─── withAutomaticReconnect ───────────────────────────────────────────────\n\n /**\n * Enable automatic reconnection on unexpected disconnections.\n *\n * @overload withAutomaticReconnect()\n * Uses the built-in delay sequence: 0 ms, 2 s, 10 s, 30 s.\n *\n * @overload withAutomaticReconnect(retryDelays: readonly number[])\n * Each element is the wait (ms) before the corresponding retry.\n * Reconnection stops after all delays are exhausted.\n * Uses `NoInfer<number>` so literals are not widened unexpectedly.\n *\n * @overload withAutomaticReconnect(policy: IRetryPolicy)\n * Custom policy. Return `null` from\n * `nextRetryDelayInMilliseconds` to stop retrying.\n */\n withAutomaticReconnect(): this;\n withAutomaticReconnect(retryDelays: readonly NoInfer<number>[]): this;\n withAutomaticReconnect(policy: IRetryPolicy): this;\n withAutomaticReconnect(\n arg?: readonly number[] | IRetryPolicy,\n ): this {\n if (arg === undefined) {\n this.#reconnectPolicy = new DefaultReconnectPolicy([...DEFAULT_RETRY_DELAYS]);\n } else if (Array.isArray(arg)) {\n this.#reconnectPolicy = new DefaultReconnectPolicy(arg);\n } else if (\n typeof arg === 'object' &&\n typeof (arg as IRetryPolicy).nextRetryDelayInMilliseconds === 'function'\n ) {\n this.#reconnectPolicy = arg as IRetryPolicy;\n } else {\n throw new TypeError(\n 'withAutomaticReconnect expects no args, a number[], or an IRetryPolicy.'\n );\n }\n return this;\n }\n\n // ─── build ───────────────────────────────────────────────────────────────\n\n build(): HubConnection {\n if (!this.#url) {\n throw new Error('withUrl() must be called before build().');\n }\n\n // If withCookies() was called, create a CookieAgent as the dispatcher so\n // that Set-Cookie headers from /negotiate are stored and Cookie headers\n // are forwarded to every subsequent request (WebSocket upgrade, SSE GET,\n // long-polling GET/POST/DELETE) - all of which share this dispatcher.\n const effectiveDispatcher: Dispatcher | null =\n this.#cookieJar !== null\n ? new CookieAgent({ cookies: { jar: this.#cookieJar } })\n : this.#dispatcher;\n\n // exactOptionalPropertyTypes: spread only defined values so we never\n // explicitly assign `undefined` to an optional property.\n const options: HubConnectionOptions = {\n ...(this.#logger != null && { logger: this.#logger }),\n ...(this.#urlOptions.accessTokenFactory != null && { accessTokenFactory: this.#urlOptions.accessTokenFactory }),\n ...(this.#urlOptions.transport != null && { transport: this.#urlOptions.transport }),\n ...(this.#urlOptions.headers != null && { headers: this.#urlOptions.headers }),\n ...(this.#urlOptions.skipNegotiation != null && { skipNegotiation: this.#urlOptions.skipNegotiation }),\n ...(this.#urlOptions.serverTimeoutInMilliseconds != null && { serverTimeoutInMilliseconds: this.#urlOptions.serverTimeoutInMilliseconds }),\n ...(this.#urlOptions.keepAliveIntervalInMilliseconds != null && { keepAliveIntervalInMilliseconds: this.#urlOptions.keepAliveIntervalInMilliseconds }),\n ...(this.#urlOptions.handshakeTimeoutInMilliseconds != null && { handshakeTimeoutInMilliseconds: this.#urlOptions.handshakeTimeoutInMilliseconds }),\n ...(this.#urlOptions.maximumReceiveMessageSize != null && { maximumReceiveMessageSize: this.#urlOptions.maximumReceiveMessageSize }),\n ...(this.#reconnectPolicy != null && { reconnectPolicy: this.#reconnectPolicy }),\n ...(effectiveDispatcher != null && { dispatcher: effectiveDispatcher }),\n ...(this.#httpClient != null && { httpClient: this.#httpClient }),\n ...(this.#protocol != null && { protocol: this.#protocol }),\n ...(this.#cookieJar != null && { ownsDispatcher: true }),\n };\n\n return new HubConnection(this.#url, options);\n }\n}\n\n// ─── Default reconnect policy ─────────────────────────────────────────────────\n\nexport class DefaultReconnectPolicy implements IRetryPolicy {\n readonly #retryDelays: readonly number[];\n\n constructor(retryDelays: readonly number[] = [...DEFAULT_RETRY_DELAYS]) {\n this.#retryDelays = retryDelays;\n }\n\n nextRetryDelayInMilliseconds(context: RetryContext): number | null {\n const delay = this.#retryDelays[context.previousRetryCount];\n return delay ?? null;\n }\n}\n","/**\n * msgpack-hub-protocol.ts\n *\n * Implements the SignalR Hub Protocol over MessagePack (version 1).\n *\n * Wire format\n * ───────────\n * • Handshake: JSON text terminated by ASCII 0x1e - identical to the JSON\n * protocol, only the \"protocol\" field changes to \"messagepack\".\n * • All subsequent messages: binary MessagePack, each frame prefixed by a\n * base-128 VarInt carrying the byte-length of the following MessagePack\n * payload. A single transport payload may contain multiple such frames.\n *\n * MessagePack array layout (per message type)\n * ────────────────────────────────────────────\n * Invocation [1, headers, invocationId|null, target, args, streamIds]\n * StreamItem [2, headers, invocationId, item]\n * Completion [3, headers, invocationId, resultKind, value?]\n * resultKind: 1 = error string, 2 = void, 3 = non-void result value\n * StreamInvocation [4, headers, invocationId, target, args, streamIds]\n * CancelInvocation [5, headers, invocationId]\n * Ping [6]\n * Close [7, error|null, allowReconnect]\n *\n * Reference:\n * https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/HubProtocol.md\n */\n\nimport { Encoder, decode } from '@msgpack/msgpack';\nimport { MessageType, TransferFormat, RECORD_SEPARATOR } from '../constants.js';\nimport type { IHubProtocol, ILogger } from '../interfaces.js';\nimport {\n type HubMessage,\n type InvocationMessage,\n type StreamInvocationMessage,\n type CancelInvocationMessage,\n type CompletionMessage,\n type StreamItemMessage,\n type PingMessage,\n type CloseMessage,\n type InvocationId,\n toInvocationId,\n} from '../messages.js';\n\n// ─── Handshake constants ──────────────────────────────────────────────────────\n\n/**\n * The JSON-formatted handshake request the client sends once the transport\n * is open. The server always responds with JSON ({} on success), regardless\n * of the chosen hub protocol.\n */\nexport const HANDSHAKE_REQUEST =\n JSON.stringify({ protocol: 'messagepack', version: 1 }) + RECORD_SEPARATOR;\n\n// The handshake *response* is always JSON - re-export the same parser that\n// JsonHubProtocol uses.\nexport {\n parseHandshakeResponse,\n type HandshakeResponse,\n type HandshakeParseResult,\n} from './json-hub-protocol.js';\n\n// ─── Completion result-kind constants ─────────────────────────────────────────\n\nconst ResultKind = Object.freeze({\n Error: 1,\n Void: 2,\n NonVoid: 3,\n} as const);\n\ntype ResultKindValue = (typeof ResultKind)[keyof typeof ResultKind];\n\n// ─── VarInt framing (base-128 variable-length integer) ───────────────────────\n\n/** Number of bytes needed to write `n` as a base-128 VarInt. */\nfunction varIntLength(n: number): number {\n let len = 1;\n while (n >= 0x80) {\n n >>>= 7;\n len++;\n }\n return len;\n}\n\n/**\n * Write `n` as a base-128 VarInt (little-endian groups of 7 bits) into\n * `out`, returning the offset just past the last byte written.\n */\nfunction writeVarInt(n: number, out: Uint8Array): number {\n let i = 0;\n while (n >= 0x80) {\n out[i++] = (n & 0x7f) | 0x80;\n n >>>= 7;\n }\n out[i++] = n;\n return i;\n}\n\n/** Read a VarInt from `data` starting at `offset`. Returns value + bytes consumed. */\nfunction readVarInt(data: Uint8Array, offset: number): { value: number; bytesRead: number } {\n let value = 0;\n let shift = 0;\n let bytesRead = 0;\n let hasMore = true;\n while (hasMore) {\n if (offset + bytesRead >= data.length) {\n throw new Error('MessagePack: unexpected end of data reading VarInt frame length.');\n }\n const byte = data[offset + bytesRead]!;\n hasMore = (byte & 0x80) !== 0;\n if (bytesRead === 4 && hasMore) {\n throw new Error('MessagePack: VarInt frame length prefix is longer than 5 bytes.');\n }\n if (bytesRead === 4 && byte > 0x07) {\n throw new Error('MessagePack: VarInt frame length exceeds the 2 GB SignalR limit.');\n }\n value |= (byte & 0x7f) << shift;\n shift += 7;\n bytesRead++;\n }\n return { value, bytesRead };\n}\n\n// ─── Frame helper: encode a MessagePack array + prepend VarInt length ─────────\n\n/**\n * One encoder reused for every frame. `encode()` from @msgpack/msgpack builds\n * a new Encoder (and a fresh 2 KB buffer) per call, which dominates the cost of\n * encoding small hub messages. Encoding is synchronous, so sharing is safe.\n */\nconst encoder = new Encoder();\n\nfunction pack(arr: unknown[]): ArrayBuffer {\n // encodeSharedRef returns a view into the encoder's internal buffer, valid\n // only until the next encode - it is copied into the frame immediately.\n const payload = encoder.encodeSharedRef(arr);\n const frame = new Uint8Array(varIntLength(payload.length) + payload.length);\n frame.set(payload, writeVarInt(payload.length, frame));\n return frame.buffer;\n}\n\n// ─── Protocol class ───────────────────────────────────────────────────────────\n\nexport class MsgpackHubProtocol implements IHubProtocol {\n readonly name = 'messagepack' as const;\n readonly version = 1 as const;\n readonly transferFormat = TransferFormat.Binary;\n\n // ─── IHubProtocol: parseMessages ─────────────────────────────────────\n\n parseMessages(input: string | ArrayBuffer, logger: ILogger): HubMessage[] {\n // The binary transport always delivers ArrayBuffer; accept string as a\n // convenience for testing (treat as UTF-8 encoded bytes).\n const raw: ArrayBuffer =\n typeof input === 'string'\n ? new TextEncoder().encode(input).buffer\n : input;\n\n const data = new Uint8Array(raw);\n if (data.length === 0) return [];\n\n const messages: HubMessage[] = [];\n let offset = 0;\n\n while (offset < data.length) {\n const { value: msgLen, bytesRead } = readVarInt(data, offset);\n offset += bytesRead;\n\n if (offset + msgLen > data.length) {\n throw new Error(\n `MessagePack hub message: declared length ${msgLen} B exceeds ` +\n `remaining data (${data.length - offset} B).`,\n );\n }\n\n const frame = data.subarray(offset, offset + msgLen);\n offset += msgLen;\n\n const rawArr = decode(frame);\n if (!Array.isArray(rawArr) || rawArr.length === 0) {\n throw new Error(\n 'Invalid MessagePack hub message: top-level value must be a non-empty array.',\n );\n }\n\n const msg = this.#coerce(rawArr, logger);\n if (msg !== null) messages.push(msg);\n }\n\n return messages;\n }\n\n // ─── IHubProtocol: writeMessage ───────────────────────────────────────\n\n writeMessage(message: HubMessage): ArrayBuffer {\n switch (message.type) {\n\n case MessageType.Invocation:\n return pack([\n MessageType.Invocation,\n message.headers ?? {},\n message.invocationId ?? null,\n message.target,\n message.arguments,\n message.streamIds ?? [],\n ]);\n\n case MessageType.StreamItem:\n return pack([\n MessageType.StreamItem,\n message.headers ?? {},\n message.invocationId,\n message.item,\n ]);\n\n case MessageType.Completion: {\n const hasError = message.error != null;\n const hasResult = Object.prototype.hasOwnProperty.call(message, 'result');\n if (hasError) {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.Error,\n message.error,\n ]);\n } else if (hasResult) {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.NonVoid,\n message.result,\n ]);\n } else {\n return pack([\n MessageType.Completion,\n message.headers ?? {},\n message.invocationId,\n ResultKind.Void,\n ]);\n }\n }\n\n case MessageType.StreamInvocation:\n return pack([\n MessageType.StreamInvocation,\n message.headers ?? {},\n message.invocationId,\n message.target,\n message.arguments,\n message.streamIds ?? [],\n ]);\n\n case MessageType.CancelInvocation:\n return pack([\n MessageType.CancelInvocation,\n message.headers ?? {},\n message.invocationId,\n ]);\n\n case MessageType.Ping:\n return pack([MessageType.Ping]);\n\n case MessageType.Close: {\n const arr: unknown[] = [MessageType.Close, message.error ?? null];\n if (message.allowReconnect !== undefined) arr.push(message.allowReconnect);\n return pack(arr);\n }\n }\n }\n\n // ─── Coercion / narrowing ─────────────────────────────────────────────\n\n /**\n * Validate and narrow a raw decoded array into a typed `HubMessage`.\n * Returns `null` for unknown types - they are logged as warnings.\n */\n #coerce(arr: unknown[], logger: ILogger): HubMessage | null {\n const type = arr[0];\n if (typeof type !== 'number') {\n throw new Error(\n `Invalid MessagePack hub message: first element (type) must be a number, ` +\n `got ${JSON.stringify(type)}.`,\n );\n }\n\n switch (type) {\n case MessageType.Invocation: return this.#coerceInvocation(arr);\n case MessageType.StreamItem: return this.#coerceStreamItem(arr);\n case MessageType.Completion: return this.#coerceCompletion(arr);\n case MessageType.StreamInvocation: return this.#coerceStreamInvocation(arr);\n case MessageType.CancelInvocation: return this.#coerceCancelInvocation(arr);\n case MessageType.Ping: return this.#coercePing();\n case MessageType.Close: return this.#coerceClose(arr);\n default:\n logger.log(3 /* Warning */, `Ignoring MessagePack message with unknown type ${String(type)}.`);\n return null;\n }\n }\n\n // ── [1, headers, invocationId|null, target, arguments, streamIds] ─────\n\n #coerceInvocation(arr: unknown[]): InvocationMessage {\n const target = arr[3];\n const args = arr[4];\n if (typeof target !== 'string') {\n throw new Error(\"Invalid Invocation message: index 3 ('target') must be a string.\");\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Invalid Invocation message: index 4 ('arguments') must be an array.\");\n }\n const rawId = arr[2];\n const rawSids = arr[5];\n const rawHdrs = arr[1];\n const streamIds = rawSids == null ? [] : parseStreamIds(rawSids);\n return {\n type: MessageType.Invocation,\n target,\n arguments: args as unknown[],\n ...(rawId != null && rawId !== '' && { invocationId: parseInvocationId(rawId) }),\n ...(streamIds.length > 0 && { streamIds }),\n ...(isNonEmptyObject(rawHdrs) && { headers: parseHeaders(rawHdrs) }),\n };\n }\n\n // ── [2, headers, invocationId, item] ─────────────────────────────────\n\n #coerceStreamItem(arr: unknown[]): StreamItemMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid StreamItem message: index 2 ('invocationId') is required.\");\n }\n return {\n type: MessageType.StreamItem,\n invocationId: parseInvocationId(rawId),\n item: arr[3],\n ...(isNonEmptyObject(arr[1]) && { headers: parseHeaders(arr[1]) }),\n };\n }\n\n // ── [3, headers, invocationId, resultKind, value?] ───────────────────\n\n #coerceCompletion(arr: unknown[]): CompletionMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid Completion message: index 2 ('invocationId') is required.\");\n }\n const invocationId = parseInvocationId(rawId);\n const resultKind = arr[3] as ResultKindValue;\n const hdrs = isNonEmptyObject(arr[1]) ? { headers: parseHeaders(arr[1]) } : {};\n\n switch (resultKind) {\n case ResultKind.Error:\n return { type: MessageType.Completion, invocationId, error: String(arr[4] ?? ''), ...hdrs };\n case ResultKind.Void:\n return { type: MessageType.Completion, invocationId, ...hdrs };\n case ResultKind.NonVoid:\n return { type: MessageType.Completion, invocationId, result: arr[4], ...hdrs };\n default:\n throw new Error(`Invalid Completion message: unknown resultKind ${String(resultKind)}.`);\n }\n }\n\n // ── [4, headers, invocationId, target, arguments, streamIds] ─────────\n\n #coerceStreamInvocation(arr: unknown[]): StreamInvocationMessage {\n const rawId = arr[2];\n const target = arr[3];\n const args = arr[4];\n if (rawId == null) {\n throw new Error(\"Invalid StreamInvocation message: index 2 ('invocationId') is required.\");\n }\n if (typeof target !== 'string') {\n throw new Error(\"Invalid StreamInvocation message: index 3 ('target') must be a string.\");\n }\n if (!Array.isArray(args)) {\n throw new Error(\"Invalid StreamInvocation message: index 4 ('arguments') must be an array.\");\n }\n const rawSids = arr[5];\n const streamIds = rawSids == null ? [] : parseStreamIds(rawSids);\n return {\n type: MessageType.StreamInvocation,\n invocationId: parseInvocationId(rawId),\n target,\n arguments: args as unknown[],\n ...(streamIds.length > 0 && { streamIds }),\n ...(isNonEmptyObject(arr[1]) && { headers: parseHeaders(arr[1]) }),\n };\n }\n\n // ── [5, headers, invocationId] ───────────────────────────────────────\n\n #coerceCancelInvocation(arr: unknown[]): CancelInvocationMessage {\n const rawId = arr[2];\n if (rawId == null) {\n throw new Error(\"Invalid CancelInvocation message: index 2 ('invocationId') is required.\");\n }\n return {\n type: MessageType.CancelInvocation,\n invocationId: parseInvocationId(rawId),\n ...(isNonEmptyObject(arr[1]) && { headers: parseHeaders(arr[1]) }),\n };\n }\n\n // ── [6] ──────────────────────────────────────────────────────────────\n\n #coercePing(): PingMessage { return { type: MessageType.Ping }; }\n\n // ── [7, error|null, allowReconnect] ──────────────────────────────────\n\n #coerceClose(arr: unknown[]): CloseMessage {\n if (arr[2] != null && typeof arr[2] !== 'boolean') {\n throw new Error(\"Invalid Close message: index 2 ('allowReconnect') must be a boolean.\");\n }\n return {\n type: MessageType.Close,\n ...(arr[1] != null && { error: String(arr[1]) }),\n ...(arr[2] != null && { allowReconnect: arr[2] }),\n };\n }\n\n // ─── Static message factories (mirrors JsonHubProtocol API) ──────────\n\n static invocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n /** Fire-and-forget (no `invocationId`). */\n static send(\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): InvocationMessage {\n return {\n type: MessageType.Invocation,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static streamInvocation(\n invocationId: InvocationId,\n target: string,\n args: readonly unknown[],\n streamIds?: readonly string[],\n ): StreamInvocationMessage {\n return {\n type: MessageType.StreamInvocation,\n invocationId,\n target,\n arguments: args,\n ...(streamIds != null && streamIds.length > 0 ? { streamIds } : {}),\n };\n }\n\n static cancelInvocation(invocationId: InvocationId): CancelInvocationMessage {\n return { type: MessageType.CancelInvocation, invocationId };\n }\n\n static streamItem(invocationId: InvocationId, item: unknown): StreamItemMessage {\n return { type: MessageType.StreamItem, invocationId, item };\n }\n\n static completion(\n invocationId: InvocationId,\n result: unknown,\n error: string | null,\n ): CompletionMessage {\n return {\n type: MessageType.Completion,\n invocationId,\n ...(error != null && { error }),\n ...(result != null && { result }),\n };\n }\n\n static ping(): PingMessage { return { type: MessageType.Ping }; }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction isNonEmptyObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v) &&\n Object.keys(v as object).length > 0;\n}\n\nfunction parseInvocationId(value: unknown): InvocationId {\n if (typeof value !== 'string') throw new Error('Invalid MessagePack message: invocationId must be a string.');\n return toInvocationId(value);\n}\n\nfunction parseStreamIds(value: unknown): string[] {\n if (!Array.isArray(value) || !value.every((entry) => typeof entry === 'string')) {\n throw new Error('Invalid MessagePack message: streamIds must be an array of strings.');\n }\n return value;\n}\n\nfunction parseHeaders(value: unknown): Record<string, string> {\n if (!isNonEmptyObject(value) || !Object.values(value).every((entry) => typeof entry === 'string')) {\n throw new Error('Invalid MessagePack message: headers must contain string values.');\n }\n return value as Record<string, string>;\n}\n","/**\n * ws-client.ts\n *\n * From-scratch WebSocket client (RFC 6455) built on Node's built-in `net`\n * and `tls` modules. Zero external runtime dependencies.\n *\n * Typed EventEmitter via interface declaration merging.\n *\n * Emitted events\n * 'open' - handshake complete, ready to send/receive\n * 'message' (string) - UTF-8 text frame received\n * 'binary' (Buffer) - binary frame received\n * 'ping' (Buffer) - ping frame received (pong sent automatically)\n * 'pong' (Buffer) - pong frame received\n * 'close' - socket fully closed\n * 'error' (Error) - socket-level error\n */\n\nimport * as net from 'node:net';\nimport * as tls from 'node:tls';\nimport * as crypto from 'node:crypto';\nimport { EventEmitter } from 'node:events';\n\n// ─── RFC 6455 opcodes ─────────────────────────────────────────────────────────\nconst enum Opcode {\n Continuation = 0x0,\n Text = 0x1,\n Binary = 0x2,\n Close = 0x8,\n Ping = 0x9,\n Pong = 0xa,\n}\n\n// ─── Connection states ────────────────────────────────────────────────────────\nexport const enum WebSocketReadyState {\n Connecting = 0,\n Open = 1,\n Closing = 2,\n Closed = 3,\n}\n\nconst WS_MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';\n\n// ─── Typed-EventEmitter overloads (declaration merging) ───────────────────────\n\nexport interface WebSocketClient {\n on(event: 'open', listener: () => void): this;\n on(event: 'message', listener: (data: string) => void): this;\n on(event: 'binary', listener: (data: Buffer) => void): this;\n on(event: 'ping', listener: (data: Buffer) => void): this;\n on(event: 'pong', listener: (data: Buffer) => void): this;\n on(event: 'close', listener: () => void): this;\n on(event: 'error', listener: (err: Error) => void): this;\n\n once(event: 'open', listener: () => void): this;\n once(event: 'message', listener: (data: string) => void): this;\n once(event: 'close', listener: () => void): this;\n once(event: 'error', listener: (err: Error) => void): this;\n\n emit(event: 'open'): boolean;\n emit(event: 'message', data: string): boolean;\n emit(event: 'binary', data: Buffer): boolean;\n emit(event: 'ping', data: Buffer): boolean;\n emit(event: 'pong', data: Buffer): boolean;\n emit(event: 'close'): boolean;\n emit(event: 'error', err: Error): boolean;\n\n removeAllListeners(event?: string): this;\n}\n\n// ─── Parsed frame ─────────────────────────────────────────────────────────────\ninterface ParsedFrame {\n fin: boolean;\n opcode: number;\n payload: Buffer;\n}\n\ninterface ParseResult {\n frame: ParsedFrame;\n consumed: number;\n}\n\n// ─── Implementation ───────────────────────────────────────────────────────────\n\nexport class WebSocketClient extends EventEmitter {\n #socket: net.Socket | null = null;\n #state: WebSocketReadyState = WebSocketReadyState.Closed;\n #frameBuf: Buffer = Buffer.alloc(0);\n #fragments: Buffer[] = [];\n #fragmentOpcode: number | null = null;\n #handshakeBuf: Buffer = Buffer.alloc(0);\n #handshakeResolve: (() => void) | null = null;\n #handshakeReject: ((e: Error) => void) | null = null;\n\n get readyState(): WebSocketReadyState { return this.#state; }\n\n // ─── Public API ─────────────────────────────────────────────────────────\n\n /**\n * Open a WebSocket connection.\n * @param url ws:// or wss:// URL\n * @param headers Extra HTTP headers for the upgrade request\n */\n connect(url: string, headers: Record<string, string> = {}): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (this.#state !== WebSocketReadyState.Closed) {\n reject(new Error('WebSocket is already open or connecting.'));\n return;\n }\n this.#state = WebSocketReadyState.Connecting;\n this.#handshakeResolve = resolve;\n this.#handshakeReject = reject;\n\n const parsed = new URL(url);\n const isSecure = parsed.protocol === 'wss:';\n const host = parsed.hostname;\n const port = Number(parsed.port) || (isSecure ? 443 : 80);\n /* istanbul ignore next -- URL normalizes an empty pathname to '/' */\n const resource = (parsed.pathname || '/') + (parsed.search || '');\n const portSuffix = parsed.port ? `:${parsed.port}` : '';\n\n const nonce = crypto.randomBytes(16).toString('base64');\n const expected = computeAccept(nonce);\n\n const upgradeLines: string[] = [\n `GET ${resource} HTTP/1.1`,\n `Host: ${host}${portSuffix}`,\n 'Upgrade: websocket',\n 'Connection: Upgrade',\n `Sec-WebSocket-Key: ${nonce}`,\n 'Sec-WebSocket-Version: 13',\n ...Object.entries(headers).map(([k, v]) => `${k}: ${v}`),\n '',\n '',\n ];\n const request = upgradeLines.join('\\r\\n');\n\n const onSocketData = (chunk: Buffer): void => {\n this.#onHandshakeData(chunk, expected);\n };\n\n const socketOpts = { host, port };\n if (isSecure) {\n this.#socket = tls.connect({ ...socketOpts, servername: host },\n /* istanbul ignore next -- identical write callback is covered via TCP */\n () => {\n this.#socket!.write(request);\n });\n } else {\n this.#socket = net.connect(socketOpts, () => {\n this.#socket!.write(request);\n });\n }\n\n this.#socket.on('data', onSocketData);\n this.#socket.on('error', (err: Error) => {\n if (this.#state === WebSocketReadyState.Connecting) {\n this.#state = WebSocketReadyState.Closed;\n this.#handshakeReject!(err);\n } else if (this.#state !== WebSocketReadyState.Closing) {\n // Errors during the Closing state (e.g. ECONNRESET after ws.close())\n // are expected and should not surface to callers.\n this.emit('error', err);\n }\n });\n this.#socket.on('close', () => this.#onSocketClose());\n this.#socket.on('end', () => this.#socket?.destroy());\n });\n }\n\n /**\n * Send a text or binary message.\n * @throws if the socket is not open.\n */\n send(data: string | Buffer | Uint8Array): void {\n if (this.#state !== WebSocketReadyState.Open) {\n throw new Error('WebSocket is not open.');\n }\n if (typeof data === 'string') {\n this.#writeFrame(Opcode.Text, Buffer.from(data, 'utf8'));\n } else {\n this.#writeFrame(Opcode.Binary, Buffer.isBuffer(data) ? data : Buffer.from(data));\n }\n }\n\n /**\n * Initiate a clean close handshake.\n * @param code WebSocket close code (default 1000 = Normal Closure)\n * @param reason UTF-8 reason string (max 123 bytes)\n */\n close(code = 1000, reason = ''): void {\n if (this.#state !== WebSocketReadyState.Open) return;\n this.#state = WebSocketReadyState.Closing;\n const reasonBuf = Buffer.from(reason, 'utf8');\n const payload = Buffer.allocUnsafe(2 + reasonBuf.length);\n payload.writeUInt16BE(code, 0);\n reasonBuf.copy(payload, 2);\n this.#writeFrame(Opcode.Close, payload);\n }\n\n // ─── Handshake ───────────────────────────────────────────────────────────\n\n #onHandshakeData(chunk: Buffer, expectedAccept: string): void {\n this.#handshakeBuf = Buffer.concat([this.#handshakeBuf, chunk]);\n\n const idx = indexOfCRLFCRLF(this.#handshakeBuf);\n if (idx === -1) return; // Wait for the full header block\n\n const headerStr = this.#handshakeBuf.subarray(0, idx).toString('ascii');\n const remainder = this.#handshakeBuf.subarray(idx + 4);\n\n const lines = headerStr.split('\\r\\n');\n /* istanbul ignore next -- split() always returns at least one element */\n const statusLine = lines[0] ?? '';\n\n if (!statusLine.includes('101')) {\n this.#failHandshake(\n new Error(`WebSocket upgrade failed - server replied: ${statusLine}`)\n );\n return;\n }\n\n let accept = '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i]!;\n const colon = line.indexOf(':');\n if (colon === -1) continue;\n if (line.slice(0, colon).trim().toLowerCase() === 'sec-websocket-accept') {\n accept = line.slice(colon + 1).trim();\n break;\n }\n }\n\n if (accept !== expectedAccept) {\n this.#failHandshake(\n new Error(`Invalid Sec-WebSocket-Accept (got \"${accept}\", expected \"${expectedAccept}\")`)\n );\n return;\n }\n\n // Success - switch to frame-processing mode\n this.#state = WebSocketReadyState.Open;\n this.#handshakeBuf = Buffer.alloc(0);\n this.#socket!.removeAllListeners('data');\n this.#socket!.on('data', (c: Buffer) => this.#onFrameData(c));\n\n const r = this.#handshakeResolve!;\n this.#handshakeResolve = null;\n this.#handshakeReject = null;\n r();\n this.emit('open');\n\n if (remainder.length > 0) this.#onFrameData(remainder);\n }\n\n #failHandshake(err: Error): void {\n this.#state = WebSocketReadyState.Closed;\n this.#socket?.destroy();\n const r = this.#handshakeReject!;\n this.#handshakeResolve = null;\n this.#handshakeReject = null;\n r(err);\n }\n\n // ─── Frame parsing ───────────────────────────────────────────────────────\n\n #onFrameData(chunk: Buffer): void {\n this.#frameBuf = Buffer.concat([this.#frameBuf, chunk]);\n this.#drainFrames();\n }\n\n #drainFrames(): void {\n for (;;) {\n const result = tryParseFrame(this.#frameBuf);\n if (!result) break;\n this.#frameBuf = this.#frameBuf.subarray(result.consumed);\n this.#dispatchFrame(result.frame);\n }\n }\n\n #dispatchFrame({ fin, opcode, payload }: ParsedFrame): void {\n switch (opcode) {\n case Opcode.Text:\n case Opcode.Binary:\n if (!fin) {\n this.#fragmentOpcode = opcode;\n this.#fragments = [payload];\n } else {\n this.#emitData(opcode, payload);\n }\n break;\n\n case Opcode.Continuation:\n this.#fragments.push(payload);\n if (fin) {\n const full = Buffer.concat(this.#fragments);\n const op = this.#fragmentOpcode!;\n this.#fragments = [];\n this.#fragmentOpcode = null;\n this.#emitData(op, full);\n }\n break;\n\n case Opcode.Ping:\n this.#writeFrame(Opcode.Pong, payload);\n this.emit('ping', payload);\n break;\n\n case Opcode.Pong:\n this.emit('pong', payload);\n break;\n\n case Opcode.Close:\n if (this.#state === WebSocketReadyState.Open) {\n this.#writeFrame(Opcode.Close, payload);\n }\n this.#state = WebSocketReadyState.Closed;\n this.#socket?.destroy();\n this.emit('close');\n break;\n\n default:\n // Unknown opcode - ignore per RFC 6455 §5.2\n break;\n }\n }\n\n #emitData(opcode: number, payload: Buffer): void {\n if (opcode === Opcode.Text) {\n this.emit('message', payload.toString('utf8'));\n } else {\n this.emit('binary', payload);\n }\n }\n\n // ─── Frame writing ───────────────────────────────────────────────────────\n\n /**\n * Encode and send one WebSocket frame.\n * All client→server frames MUST be masked (RFC 6455 §5.3).\n */\n #writeFrame(\n opcode: Opcode,\n payload: Buffer,\n ): void {\n /* istanbul ignore next -- public methods validate state before writing */\n if (!this.#socket || this.#socket.destroyed) return;\n\n const len = payload.length;\n\n // ── Header ──────────────────────────────────────────────────────────\n let header: Buffer;\n if (len < 126) {\n header = Buffer.allocUnsafe(2);\n header[1] = 0x80 | len; // MASK bit + length\n } else if (len < 65_536) {\n header = Buffer.allocUnsafe(4);\n header[1] = 0x80 | 126;\n header.writeUInt16BE(len, 2);\n } else {\n header = Buffer.allocUnsafe(10);\n header[1] = 0x80 | 127;\n header.writeUInt32BE(0, 2);\n header.writeUInt32BE(len, 6);\n }\n header[0] = 0x80 | opcode; // all outbound frames are complete (FIN)\n\n // ── Masking ─────────────────────────────────────────────────────────\n const maskKey = crypto.randomBytes(4);\n const maskedPayload = Buffer.allocUnsafe(len);\n for (let i = 0; i < len; i++) {\n maskedPayload[i] = payload[i]! ^ maskKey[i % 4]!;\n }\n\n this.#socket.write(Buffer.concat([header, maskKey, maskedPayload]));\n }\n\n // ─── Socket events ───────────────────────────────────────────────────────\n\n #onSocketClose(): void {\n if (this.#state !== WebSocketReadyState.Closed) {\n this.#state = WebSocketReadyState.Closed;\n this.emit('close');\n }\n }\n}\n\n// ─── Module-level helpers ─────────────────────────────────────────────────────\n\nfunction computeAccept(key: string): string {\n return crypto.createHash('sha1').update(key + WS_MAGIC).digest('base64');\n}\n\nfunction indexOfCRLFCRLF(buf: Buffer): number {\n for (let i = 0; i <= buf.length - 4; i++) {\n if (buf[i] === 0x0d && buf[i + 1] === 0x0a &&\n buf[i + 2] === 0x0d && buf[i + 3] === 0x0a) {\n return i;\n }\n }\n return -1;\n}\n\nfunction tryParseFrame(buf: Buffer): ParseResult | null {\n if (buf.length < 2) return null;\n\n const b0 = buf[0]!;\n const b1 = buf[1]!;\n const fin = (b0 & 0x80) !== 0;\n const opcode = b0 & 0x0f;\n const masked = (b1 & 0x80) !== 0;\n let payLen = b1 & 0x7f;\n let offset = 2;\n\n if (payLen === 126) {\n if (buf.length < offset + 2) return null;\n payLen = buf.readUInt16BE(offset);\n offset += 2;\n } else if (payLen === 127) {\n if (buf.length < offset + 8) return null;\n const hi = buf.readUInt32BE(offset);\n /* istanbul ignore next -- allocating a >4 GB test frame is impractical */\n if (hi !== 0) throw new Error('Received a frame with payload > 4 GB - not supported.');\n payLen = buf.readUInt32BE(offset + 4);\n offset += 8;\n }\n\n let maskBytes: Buffer | null = null;\n if (masked) {\n if (buf.length < offset + 4) return null;\n maskBytes = buf.subarray(offset, offset + 4);\n offset += 4;\n }\n\n if (buf.length < offset + payLen) return null;\n\n let payload = buf.subarray(offset, offset + payLen);\n if (masked && maskBytes !== null) {\n payload = Buffer.from(payload);\n for (let i = 0; i < payload.length; i++) {\n // noUncheckedIndexedAccess: both sides are within-bounds by construction\n payload[i] = (payload[i] as number) ^ (maskBytes[i % 4] as number);\n }\n }\n\n return { frame: { fin, opcode, payload }, consumed: offset + payLen };\n}\n"],"mappings":"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"}