# @probitas/client-connectrpc > Version: 0.7.0 ConnectRPC client for [Probitas](https://github.com/probitas-test/probitas) scenario testing framework. This package provides a ConnectRPC-based client with Server Reflection support, designed for integration testing of gRPC and Connect protocol services. ## Features - **Protocol Support**: Connect, gRPC, and gRPC-Web protocols - **Server Reflection**: Auto-discover services and methods at runtime - **TLS Support**: Configure secure connections with custom certificates - **Duration Tracking**: Built-in timing for performance monitoring - **Error Handling**: Test error responses without throwing exceptions - **Resource Management**: Implements `AsyncDisposable` for proper cleanup ## Installation ```bash deno add jsr:@probitas/client-connectrpc ``` ## Quick Start ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; // Create client (uses reflection by default) const client = createConnectRpcClient({ url: "http://localhost:50051", }); // Discover services via reflection const services = await client.reflection.listServices(); console.log("Available services:", services); // Get service info const info = await client.reflection.getServiceInfo("echo.EchoService"); console.log("Methods:", info.methods); // Call a method const response = await client.call( "echo.EchoService", "echo", { message: "Hello!" } ); console.log(response.data); await client.close(); ``` ## Testing Error Responses ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; const client = createConnectRpcClient({ url: "http://localhost:50051" }); // Test error responses without throwing const errorResponse = await client.call( "echo.EchoService", "echo", { invalid: true }, { throwOnError: false } ); if (!errorResponse.ok) { console.log("Error code:", errorResponse.statusCode); // INVALID_ARGUMENT = 3 } await client.close(); ``` ## Using with `using` Statement ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; await using client = createConnectRpcClient({ url: "http://localhost:50051" }); const res = await client.call("echo.EchoService", "echo", { message: "test" }); console.log(res.data); // Client automatically closed when block exits ``` ## Related Packages | Package | Description | |---------|-------------| | [`@probitas/client`](https://jsr.io/@probitas/client) | Core utilities and types | | [`@probitas/client-grpc`](https://jsr.io/@probitas/client-grpc) | gRPC client (wrapper with `protocol: "grpc"`) | ## Links - [GitHub Repository](https://github.com/probitas-test/probitas-client) - [Probitas Framework](https://github.com/probitas-test/probitas) - [ConnectRPC](https://connectrpc.com/) ## Classes ### `ConnectRpcNetworkError` ```typescript class ConnectRpcNetworkError extends ClientError ``` Error thrown when a network-level failure occurs. This error indicates that the request could not be processed by the server due to network issues (connection refused, DNS resolution failure, timeout, etc.). Unlike ConnectRpcError, this error means the server was never reached. **Constructor:** ```typescript new ConnectRpcNetworkError(message: string, options?: ErrorOptions) ``` **Properties:** - [readonly] `name`: `string` - [readonly] `kind`: `"connectrpc"` --- ### `ConnectRpcError` ```typescript class ConnectRpcError extends ClientError ``` Error class for ConnectRPC/gRPC errors. Use `statusCode` to distinguish between different gRPC error codes. **Constructor:** ```typescript new ConnectRpcError( message: string, statusCode: ConnectRpcStatusCode, statusMessage: string, options?: ConnectRpcErrorOptions, ) ``` **Properties:** - [readonly] `name`: `string` - [readonly] `kind`: `"connectrpc"` - [readonly] `statusCode`: `ConnectRpcStatusCode` - [readonly] `statusMessage`: `string` - [readonly] `metadata`: `Headers | null` - [readonly] `details`: `readonly ErrorDetail[]` --- ## Interfaces ### `ConnectRpcResponseError` ```typescript interface ConnectRpcResponseError extends ConnectRpcResponseBase ``` ConnectRPC response with gRPC error (statusCode !== 0). The server processed the request but returned an error status. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `ConnectRpcError` - [readonly] `statusCode`: `ConnectRpcStatusCode` — gRPC status code (1-16). - [readonly] `statusMessage`: `string` — Status message describing the error. - [readonly] `headers`: `Headers` — Response headers. - [readonly] `trailers`: `Headers` — Response trailers (sent at end of RPC). - [readonly] `raw`: `ConnectError` — Raw ConnectError. - [readonly] `data`: `null` — No data for error responses. --- ### `ConnectRpcResponseFailure` ```typescript interface ConnectRpcResponseFailure extends ConnectRpcResponseBase ``` Failed ConnectRPC request (network error, connection refused, etc.). The request did not reach gRPC processing. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `ConnectRpcFailureError` - [readonly] `statusCode`: `null` — Status code (null for network failures). - [readonly] `statusMessage`: `null` — Status message (null for network failures). - [readonly] `headers`: `null` — Response headers (null for failures). - [readonly] `trailers`: `null` — Response trailers (null for failures). - [readonly] `raw`: `null` — No raw response (request didn't reach server). - [readonly] `data`: `null` — No data (request didn't reach server). --- ### `ConnectRpcResponseSuccess` ```typescript interface ConnectRpcResponseSuccess extends ConnectRpcResponseBase ``` Successful ConnectRPC response (statusCode === 0). **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` - [readonly] `statusCode`: `0` — gRPC status code (always 0 for success). - [readonly] `statusMessage`: `null` — Status message (null for successful responses). - [readonly] `headers`: `Headers` — Response headers. - [readonly] `trailers`: `Headers` — Response trailers (sent at end of RPC). - [readonly] `raw`: `unknown` — Raw protobuf Message object. - [readonly] `data`: `T | null` — Response data as plain JavaScript object (JSON representation). --- ### `TlsConfig` ```typescript interface TlsConfig ``` TLS configuration for ConnectRPC connections. **Properties:** - [readonly] `rootCerts?`: `Uint8Array` — Root CA certificate (PEM format). - [readonly] `clientCert?`: `Uint8Array` — Client certificate (PEM format). - [readonly] `clientKey?`: `Uint8Array` — Client private key (PEM format). - [readonly] `insecure?`: `boolean` — Skip server certificate verification (use only for testing). --- ### `ConnectRpcConnectionConfig` ```typescript interface ConnectRpcConnectionConfig extends CommonConnectionConfig ``` ConnectRPC connection configuration. Extends CommonConnectionConfig with ConnectRPC-specific options. **Properties:** - [readonly] `protocol?`: `"http" | "https"` — Protocol to use. - [readonly] `path?`: `string` — Service path prefix. --- ### `ConnectRpcClientConfig` ```typescript interface ConnectRpcClientConfig extends CommonOptions ``` Configuration for creating a ConnectRPC client. **Properties:** - [readonly] `url`: `string | ConnectRpcConnectionConfig` — Server URL for ConnectRPC connections. Can be a URL string or a connection configuration object. - [readonly] `protocol?`: `ConnectProtocol` — Protocol to use. - [readonly] `httpVersion?`: `HttpVersion` — HTTP version to use. - [readonly] `tls?`: `TlsConfig` — TLS configuration. If not provided, uses insecure credentials. - [readonly] `metadata?`: `HeadersInit` — Default metadata to send with every request. - [readonly] `schema?`: `"reflection" | string | Uint8Array | FileDescriptorSet` — Schema resolution configuration. - "reflection": Use Server Reflection to discover services dynamically (default) - string: Path to FileDescriptorSet binary file (from `buf build --output set.binpb`) - Uint8Array: FileDescriptorSet binary data - FileDescriptorSet: Pre-parsed FileDescriptorSet message object - [readonly] `useBinaryFormat?`: `boolean` — Whether to use binary format for messages. - [readonly] `throwOnError?`: `boolean` — Whether to throw ConnectRpcError on non-OK responses (code !== 0) or failures. Can be overridden per-request via ConnectRpcOptions.throwOnError. --- ### `ConnectRpcOptions` ```typescript interface ConnectRpcOptions extends CommonOptions ``` Options for individual ConnectRPC calls. **Properties:** - [readonly] `metadata?`: `HeadersInit` — Metadata to send with the request. - [readonly] `throwOnError?`: `boolean` — Whether to throw ConnectRpcError on non-OK responses (code !== 0) or failures. Overrides ConnectRpcClientConfig.throwOnError. --- ### `ServiceInfo` ```typescript interface ServiceInfo ``` Service information from reflection. **Properties:** - [readonly] `name`: `string` — Fully qualified service name (e.g., "echo.EchoService") - [readonly] `file`: `string` — Proto file name --- ### `MethodInfo` ```typescript interface MethodInfo ``` Method information from reflection. **Properties:** - [readonly] `name`: `string` — Method name (e.g., "Echo") - [readonly] `localName`: `string` — Local name (camelCase) - [readonly] `kind`: `"unary" | "server_streaming" | "client_streaming" | "bidi_streaming"` — Method kind - [readonly] `inputType`: `string` — Input message type name - [readonly] `outputType`: `string` — Output message type name - [readonly] `idempotent`: `boolean` — Whether the method is idempotent --- ### `ServiceDetail` ```typescript interface ServiceDetail ``` Detailed service information. **Properties:** - [readonly] `name`: `string` — Service name - [readonly] `fullName`: `string` — Fully qualified service name - [readonly] `packageName`: `string` — Package name - [readonly] `protoFile`: `string` — Proto file name - [readonly] `methods`: `readonly MethodInfo[]` — All methods --- ### `ErrorDetail` ```typescript interface ErrorDetail ``` Rich error detail from google.rpc.Status. ConnectRPC errors can include structured details encoded in error responses. These details follow the google.protobuf.Any format with a type URL and value. **Properties:** - [readonly] `typeUrl`: `string` — Type URL identifying the error detail type. Common types include: - "type.googleapis.com/google.rpc.BadRequest" - "type.googleapis.com/google.rpc.DebugInfo" - "type.googleapis.com/google.rpc.RetryInfo" - "type.googleapis.com/google.rpc.QuotaFailure" - [readonly] `value`: `unknown` — Decoded error detail value. The structure depends on the typeUrl. --- ### `ConnectRpcErrorOptions` ```typescript interface ConnectRpcErrorOptions extends ErrorOptions ``` Options for ConnectRpcError construction. **Properties:** - [readonly] `metadata?`: `Headers | null` — Headers/metadata from the ConnectRPC response. - [readonly] `details?`: `readonly ErrorDetail[] | null` — Rich error details from google.rpc.Status. --- ### `ConnectRpcResponseSuccessParams` ```typescript interface ConnectRpcResponseSuccessParams ``` Parameters for creating a successful ConnectRpcResponse. **Properties:** - [readonly] `response`: `T | null` - [readonly] `schema`: `DescMessage | null` - [readonly] `headers`: `Headers` - [readonly] `trailers`: `Headers` - [readonly] `duration`: `number` --- ### `ConnectRpcResponseErrorParams` ```typescript interface ConnectRpcResponseErrorParams ``` Parameters for creating an error ConnectRpcResponse. **Properties:** - [readonly] `error`: `ConnectError` - [readonly] `rpcError`: `ConnectRpcError` - [readonly] `headers`: `Headers` - [readonly] `trailers`: `Headers` - [readonly] `duration`: `number` --- ### `ConnectRpcResponseFailureParams` ```typescript interface ConnectRpcResponseFailureParams ``` Parameters for creating a failure ConnectRpcResponse. **Properties:** - [readonly] `error`: `ConnectRpcFailureError` - [readonly] `duration`: `number` --- ### `ReflectionApi` ```typescript interface ReflectionApi ``` Reflection API for ConnectRPC client. Only available when client is created with schema: "reflection". **Properties:** - [readonly] `enabled`: `boolean` — Check if reflection is enabled. **Methods:** ```typescript listServices(): Promise ``` List all available services on the server. ```typescript getServiceInfo(serviceName: string): Promise ``` Get detailed information about a specific service. ```typescript listMethods(serviceName: string): Promise ``` Get methods for a specific service. ```typescript hasService(serviceName: string): Promise ``` Check if a service exists. --- ### `ConnectRpcClient` ```typescript interface ConnectRpcClient extends AsyncDisposable ``` ConnectRPC client interface. ## Field Name Conventions This client automatically handles field name conversion between protobuf and JavaScript: - **Request fields**: Accept both `snake_case` (protobuf style) and `camelCase` (JavaScript style) - **Response fields**: Converted to JavaScript conventions based on response type: - `response.data`: Plain JSON object with `camelCase` field names (no `$typeName`) - `response.raw`: Original protobuf Message object with all metadata (includes `$typeName`) **Properties:** - [readonly] `config`: `ConnectRpcClientConfig` — Client configuration - [readonly] `reflection`: `ReflectionApi` — Reflection API (only available when schema: "reflection") **Methods:** ```typescript call( serviceName: string, methodName: string, request: TRequest, options?: ConnectRpcOptions, ): Promise ``` Make a unary RPC call. ```typescript serverStream( serviceName: string, methodName: string, request: TRequest, options?: ConnectRpcOptions, ): AsyncIterable ``` Make a server streaming RPC call. ```typescript clientStream( serviceName: string, methodName: string, requests: AsyncIterable, options?: ConnectRpcOptions, ): Promise ``` Make a client streaming RPC call. ```typescript bidiStream( serviceName: string, methodName: string, requests: AsyncIterable, options?: ConnectRpcOptions, ): AsyncIterable ``` Make a bidirectional streaming RPC call. ```typescript close(): Promise ``` Close the client connection. **Example:** ```ts const client = createConnectRpcClient({ url: "http://localhost:50051" }); // Request: Both formats work await client.call("echo.Echo", "echoWithDelay", { message: "hello", delayMs: 100, // camelCase (recommended) // delay_ms: 100, // snake_case also works }); // Response: data is JSON, raw is protobuf Message const response = await client.call("echo.Echo", "echo", { message: "test" }); console.log(response.data); // { message: "test", metadata: {...} } console.log(response.raw); // { $typeName: "echo.EchoResponse", message: "test", ... } ``` --- ## Functions ### `getStatusName` ```typescript function getStatusName(code: ConnectRpcStatusCode): string ``` Get the name of a ConnectRPC/gRPC status code. **Parameters:** - `code`: `ConnectRpcStatusCode` **Returns:** `string` **Example:** ```typescript getStatusName(0); // "OK" getStatusName(5); // "NOT_FOUND" getStatusName(16); // "UNAUTHENTICATED" ``` --- ### `isConnectRpcStatusCode` ```typescript function isConnectRpcStatusCode(code: number): code is ConnectRpcStatusCode ``` Check if a number is a valid ConnectRPC/gRPC status code. **Parameters:** - `code`: `number` **Returns:** `code is ConnectRpcStatusCode` **Example:** ```typescript isConnectRpcStatusCode(0); // true isConnectRpcStatusCode(16); // true isConnectRpcStatusCode(99); // false ``` --- ### `fromConnectError` ```typescript function fromConnectError( error: ConnectError, metadata?: Headers, ): ConnectRpcError ``` Convert ConnectRPC's ConnectError to ConnectRpcError. **Parameters:** - `error`: `ConnectError` — - The ConnectError from @connectrpc/connect - `metadata`: `Headers` (optional) — - Optional metadata from the response **Returns:** `ConnectRpcError` ConnectRpcError with statusCode for discrimination --- ### `createConnectRpcClient` ```typescript function createConnectRpcClient( config: ConnectRpcClientConfig, ): ConnectRpcClient ``` Create a new ConnectRPC client instance. The client supports multiple protocols (Connect, gRPC, gRPC-Web) and provides Server Reflection for runtime service discovery without compile-time code generation. **Parameters:** - `config`: `ConnectRpcClientConfig` — - Client configuration including server URL and protocol options **Returns:** `ConnectRpcClient` A new ConnectRPC client instance **Example:** Basic usage with reflection ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; const client = createConnectRpcClient({ url: "http://localhost:50051", }); // Call a method const response = await client.call( "echo.EchoService", "echo", { message: "Hello!" } ); console.log(response.data); await client.close(); ``` Service discovery with reflection ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; const client = createConnectRpcClient({ url: "http://localhost:50051", }); // Discover available services const services = await client.reflection.listServices(); console.log("Services:", services); // Get method information const info = await client.reflection.getServiceInfo("echo.EchoService"); console.log("Methods:", info.methods); await client.close(); ``` Using different protocols ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; // Connect protocol (HTTP/1.1 or HTTP/2) const connectClient = createConnectRpcClient({ url: "http://localhost:8080", protocol: "connect", }); // gRPC protocol (HTTP/2 with binary protobuf) const grpcClient = createConnectRpcClient({ url: "http://localhost:50051", protocol: "grpc", }); // gRPC-Web protocol (for browser compatibility) const grpcWebClient = createConnectRpcClient({ url: "http://localhost:8080", protocol: "grpc-web", }); await connectClient.close(); await grpcClient.close(); await grpcWebClient.close(); ``` Using connection config object ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; const client = createConnectRpcClient({ url: { host: "grpc.example.com", port: 443, protocol: "https", }, }); await client.close(); ``` Using `await using` for automatic cleanup ```ts import { createConnectRpcClient } from "@probitas/client-connectrpc"; await using client = createConnectRpcClient({ url: "http://localhost:50051", }); const res = await client.call("echo.EchoService", "echo", { message: "test" }); // Client automatically closed when scope exits ``` --- ## Types ### `ConnectRpcResponse` ```typescript type ConnectRpcResponse = ConnectRpcResponseSuccess | ConnectRpcResponseError | ConnectRpcResponseFailure ``` ConnectRPC response union type. Use `processed` to distinguish between server responses and failures: - `processed === true`: Server responded (Success or Error) - `processed === false`: Request failed (Failure) Use `ok` to check for success: - `ok === true`: Success (statusCode === 0) - `ok === false`: Error or Failure --- ### `FileDescriptorSet` ```typescript type FileDescriptorSet = MessageShape ``` FileDescriptorSet message type from @bufbuild/protobuf. This is the decoded protobuf message containing file descriptors. --- ### `ConnectProtocol` ```typescript type ConnectProtocol = "connect" | "grpc" | "grpc-web" ``` Protocol to use for ConnectRPC transport. --- ### `HttpVersion` ```typescript type HttpVersion = "1.1" | "2" ``` HTTP version for transport. --- ### `ConnectRpcStatusCode` ```typescript type ConnectRpcStatusCode = unknown ``` ConnectRPC/gRPC status code type. Derived from ConnectRpcStatus values. --- ### `ConnectRpcFailureError` ```typescript type ConnectRpcFailureError = ConnectRpcNetworkError | AbortError | TimeoutError ``` Error types that indicate the operation was not processed. These are errors that occur before the request reaches the server. --- ### `ConnectRpcErrorType` ```typescript type ConnectRpcErrorType = ConnectRpcError | ConnectRpcNetworkError ``` ConnectRPC error type union. Contains either: - ConnectRpcError: gRPC error returned by the server - ConnectRpcNetworkError: Network-level failure before reaching the server --- ## Variables ### `ConnectRpcStatus` ```typescript const ConnectRpcStatus: { OK: number; CANCELLED: number; UNKNOWN: number; INVALID_ARGUMENT: number; DEADLINE_EXCEEDED: number; NOT_FOUND: number; ALREADY_EXISTS: number; PERMISSION_DENIED: number; RESOURCE_EXHAUSTED: number; FAILED_PRECONDITION: number; ABORTED: number; OUT_OF_RANGE: number; UNIMPLEMENTED: number; INTERNAL: number; UNAVAILABLE: number; DATA_LOSS: number; UNAUTHENTICATED: number; } ``` ConnectRPC/gRPC status codes. These codes are used by both gRPC and ConnectRPC protocols. --- ## Related Links ### This Package - [`ConnectProtocol`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectProtocol) - [`ConnectRpcClient`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcClient) - [`ConnectRpcClientConfig`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcClientConfig) - [`ConnectRpcConnectionConfig`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcConnectionConfig) - [`ConnectRpcError`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcError) - [`ConnectRpcErrorOptions`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcErrorOptions) - [`ConnectRpcFailureError`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcFailureError) - [`ConnectRpcNetworkError`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcNetworkError) - [`ConnectRpcOptions`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcOptions) - [`ConnectRpcResponse`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcResponse) - [`ConnectRpcResponseError`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcResponseError) - [`ConnectRpcResponseFailure`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcResponseFailure) - [`ConnectRpcResponseSuccess`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcResponseSuccess) - [`ConnectRpcStatusCode`](https://probitas-test.github.io/documents/api/client-connectrpc#ConnectRpcStatusCode) - [`ErrorDetail`](https://probitas-test.github.io/documents/api/client-connectrpc#ErrorDetail) - [`FileDescriptorSet`](https://probitas-test.github.io/documents/api/client-connectrpc#FileDescriptorSet) - [`HttpVersion`](https://probitas-test.github.io/documents/api/client-connectrpc#HttpVersion) - [`MethodInfo`](https://probitas-test.github.io/documents/api/client-connectrpc#MethodInfo) - [`ReflectionApi`](https://probitas-test.github.io/documents/api/client-connectrpc#ReflectionApi) - [`ServiceDetail`](https://probitas-test.github.io/documents/api/client-connectrpc#ServiceDetail) - [`ServiceInfo`](https://probitas-test.github.io/documents/api/client-connectrpc#ServiceInfo) - [`TlsConfig`](https://probitas-test.github.io/documents/api/client-connectrpc#TlsConfig) ### Other Packages - [`AbortError`](https://probitas-test.github.io/documents/api/client#AbortError) (@probitas/client) - [`CommonConnectionConfig`](https://probitas-test.github.io/documents/api/client#CommonConnectionConfig) (@probitas/client) - [`CommonOptions`](https://probitas-test.github.io/documents/api/client#CommonOptions) (@probitas/client) - [`TimeoutError`](https://probitas-test.github.io/documents/api/client#TimeoutError) (@probitas/client) ### Built-in Types - [`AsyncIterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols) - [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) - [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) --- *Last updated: 2026-01-12*