@probitas/client-grpc

gRPC client for Probitas scenario testing framework.

This package provides a gRPC client with Server Reflection support, designed for integration testing of gRPC services. It is a thin wrapper around `@probitas/client-connectrpc` with protocol: "grpc" pre-configured.

Features

  • Native gRPC: Uses gRPC protocol (HTTP/2 with binary protobuf)
  • Server Reflection: Auto-discover services and methods at runtime
  • Field Name Conversion: Automatic snake_case ↔ camelCase conversion
  • 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

deno add jsr:@probitas/client-grpc

Quick Start

import { createGrpcClient } from "@probitas/client-grpc";

// Create client (uses reflection by default)
const client = createGrpcClient({
  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

import { createGrpcClient } from "@probitas/client-grpc";

const client = createGrpcClient({ 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();

Field Name Conventions

The client automatically handles field name conversion between protobuf and JavaScript:

  • Request: Accept both snake_case (protobuf) and camelCase (JavaScript) field names
  • Response:
    • response.data — Plain JSON with camelCase fields (no $typeName)
    • response.raw — Original protobuf Message with metadata (includes $typeName)
import { createGrpcClient } from "@probitas/client-grpc";

const client = createGrpcClient({ url: "http://localhost:50051" });

// Request: Both camelCase and snake_case work
const response = await client.call("echo.Echo", "echoWithDelay", {
  message: "hello",
  delayMs: 100,        // camelCase (recommended for JavaScript)
  // delay_ms: 100,    // snake_case (protobuf style) also works
});

// Response data: JSON with camelCase fields
console.log(response.data);
// { message: "hello", metadata: {...} }  ← no $typeName

// Response raw: protobuf Message with metadata
console.log(response.raw);
// { $typeName: "echo.EchoResponse", message: "hello", ... }

await client.close();

Using with using Statement

import { createGrpcClient } from "@probitas/client-grpc";

await using client = createGrpcClient({ url: "http://localhost:50051" });

const res = await client.call("echo.EchoService", "echo", { message: "test" });
console.log(res.data);
// Client automatically closed when block exits
PackageDescription
`@probitas/client`Core utilities and types
`@probitas/client-connectrpc`ConnectRPC client (supports Connect, gRPC, gRPC-Web)

Installation

deno add jsr:@probitas/client-grpc

Classes

class

#GrpcError

class GrpcError extends ClientError

Error class for ConnectRPC/gRPC errors.

Use statusCode to distinguish between different gRPC error codes.

NameDescription
name
kind
statusCode
statusMessage
metadata
details
Constructor
new GrpcError(
  message: string,
  statusCode: ConnectRpcStatusCode,
  statusMessage: string,
  options?: ConnectRpcErrorOptions,
)
Properties
  • readonlynamestring
  • readonlykind"connectrpc"
  • readonlystatusCodeConnectRpcStatusCode
  • readonlystatusMessagestring
  • readonlymetadataHeaders | null
  • readonlydetailsreadonly ErrorDetail[]
class

#GrpcNetworkError

class GrpcNetworkError 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.

NameDescription
name
kind
Constructor
new GrpcNetworkError(message: string, options?: ErrorOptions)
Properties
  • readonlynamestring
  • readonlykind"connectrpc"

Interfaces

interface

#ErrorDetail

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.

NameDescription
typeUrlType URL identifying the error detail type.
valueDecoded error detail value.
Properties
  • readonlytypeUrlstring

    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"
  • readonlyvalueunknown

    Decoded error detail value. The structure depends on the typeUrl.

interface

#GrpcClient

interface GrpcClient 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)
Examples
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", ... }
NameDescription
configClient configuration
reflectionReflection API (only available when schema: "reflection")
call()Make a unary RPC call.
serverStream()Make a server streaming RPC call.
clientStream()Make a client streaming RPC call.
bidiStream()Make a bidirectional streaming RPC call.
close()Close the client connection.
Properties
Methods
call<TRequest>(
  serviceName: string,
  methodName: string,
  request: TRequest,
  options?: ConnectRpcOptions,
): Promise<ConnectRpcResponse>

Make a unary RPC call.

Parameters
  • serviceNamestring
    • Service name (e.g., "echo.EchoService")
  • methodNamestring
    • Method name (e.g., "echo")
  • requestTRequest
    • Request message
    • Call options
serverStream<TRequest>(
  serviceName: string,
  methodName: string,
  request: TRequest,
  options?: ConnectRpcOptions,
): AsyncIterable<ConnectRpcResponse>

Make a server streaming RPC call.

Parameters
  • serviceNamestring
    • Service name
  • methodNamestring
    • Method name
  • requestTRequest
    • Request message
    • Call options
clientStream<TRequest>(
  serviceName: string,
  methodName: string,
  requests: AsyncIterable<TRequest>,
  options?: ConnectRpcOptions,
): Promise<ConnectRpcResponse>

Make a client streaming RPC call.

Parameters
  • serviceNamestring
    • Service name
  • methodNamestring
    • Method name
  • requestsAsyncIterable<TRequest>
    • Async iterable of request messages
    • Call options
bidiStream<TRequest>(
  serviceName: string,
  methodName: string,
  requests: AsyncIterable<TRequest>,
  options?: ConnectRpcOptions,
): AsyncIterable<ConnectRpcResponse>

Make a bidirectional streaming RPC call.

Parameters
  • serviceNamestring
    • Service name
  • methodNamestring
    • Method name
  • requestsAsyncIterable<TRequest>
    • Async iterable of request messages
    • Call options
close(): Promise<void>

Close the client connection.

interface

#GrpcClientConfig

interface GrpcClientConfig extends Omit<ConnectRpcClientConfig, "protocol">

Configuration for creating a gRPC client.

This is a subset of ConnectRpcClientConfig with protocol fixed to "grpc".

interface

#GrpcErrorOptions

interface GrpcErrorOptions extends ErrorOptions

Options for ConnectRpcError construction.

NameDescription
metadataHeaders/metadata from the ConnectRPC response.
detailsRich error details from google.rpc.Status.
Properties
  • readonlymetadata?Headers | null

    Headers/metadata from the ConnectRPC response.

  • readonlydetails?readonly ErrorDetail[] | null

    Rich error details from google.rpc.Status.

interface

#GrpcOptions

interface GrpcOptions extends CommonOptions

Options for individual ConnectRPC calls.

NameDescription
metadataMetadata to send with the request.
throwOnErrorWhether to throw ConnectRpcError on non-OK responses (code !== 0) or failures.
Properties
  • readonlymetadata?HeadersInit

    Metadata to send with the request.

  • readonlythrowOnError?boolean

    Whether to throw ConnectRpcError on non-OK responses (code !== 0) or failures. Overrides ConnectRpcClientConfig.throwOnError.

interface

#GrpcResponseError

interface GrpcResponseError<T = any> extends ConnectRpcResponseBase<T>

ConnectRPC response with gRPC error (statusCode !== 0).

The server processed the request but returned an error status.

NameDescription
processed
ok
error
statusCodegRPC status code (1-16).
statusMessageStatus message describing the error.
headersResponse headers.
trailersResponse trailers (sent at end of RPC).
rawRaw ConnectError.
dataNo data for error responses.
Properties
  • readonlyprocessedtrue
  • readonlyokfalse
  • readonlyerrorConnectRpcError
  • readonlystatusCodeConnectRpcStatusCode

    gRPC status code (1-16).

  • readonlystatusMessagestring

    Status message describing the error.

  • readonlyheadersHeaders

    Response headers.

  • readonlytrailersHeaders

    Response trailers (sent at end of RPC).

  • readonlyrawConnectError

    Raw ConnectError.

  • readonlydatanull

    No data for error responses.

interface

#GrpcResponseFailure

interface GrpcResponseFailure<T = any> extends ConnectRpcResponseBase<T>

Failed ConnectRPC request (network error, connection refused, etc.).

The request did not reach gRPC processing.

NameDescription
processed
ok
error
statusCodeStatus code (null for network failures).
statusMessageStatus message (null for network failures).
headersResponse headers (null for failures).
trailersResponse trailers (null for failures).
rawNo raw response (request didn't reach server).
dataNo data (request didn't reach server).
Properties
  • readonlyprocessedfalse
  • readonlyokfalse
  • readonlystatusCodenull

    Status code (null for network failures).

  • readonlystatusMessagenull

    Status message (null for network failures).

  • readonlyheadersnull

    Response headers (null for failures).

  • readonlytrailersnull

    Response trailers (null for failures).

  • readonlyrawnull

    No raw response (request didn't reach server).

  • readonlydatanull

    No data (request didn't reach server).

interface

#GrpcResponseSuccess

interface GrpcResponseSuccess<T = any> extends ConnectRpcResponseBase<T>

Successful ConnectRPC response (statusCode === 0).

NameDescription
processed
ok
error
statusCodegRPC status code (always 0 for success).
statusMessageStatus message (null for successful responses).
headersResponse headers.
trailersResponse trailers (sent at end of RPC).
rawRaw protobuf Message object.
dataResponse data as plain JavaScript object (JSON representation).
Properties
  • readonlyprocessedtrue
  • readonlyoktrue
  • readonlyerrornull
  • readonlystatusCode0

    gRPC status code (always 0 for success).

  • readonlystatusMessagenull

    Status message (null for successful responses).

  • readonlyheadersHeaders

    Response headers.

  • readonlytrailersHeaders

    Response trailers (sent at end of RPC).

  • readonlyrawunknown

    Raw protobuf Message object.

  • readonlydataT | null

    Response data as plain JavaScript object (JSON representation).

interface

#MethodInfo

interface MethodInfo

Method information from reflection.

NameDescription
nameMethod name (e.g., "Echo")
localNameLocal name (camelCase)
kindMethod kind
inputTypeInput message type name
outputTypeOutput message type name
idempotentWhether the method is idempotent
Properties
  • readonlynamestring

    Method name (e.g., "Echo")

  • readonlylocalNamestring

    Local name (camelCase)

  • readonlykind"unary" | "server_streaming" | "client_streaming" | "bidi_streaming"

    Method kind

  • readonlyinputTypestring

    Input message type name

  • readonlyoutputTypestring

    Output message type name

  • readonlyidempotentboolean

    Whether the method is idempotent

interface

#ReflectionApi

interface ReflectionApi

Reflection API for ConnectRPC client. Only available when client is created with schema: "reflection".

NameDescription
enabledCheck if reflection is enabled.
listServices()List all available services on the server.
getServiceInfo()Get detailed information about a specific service.
listMethods()Get methods for a specific service.
hasService()Check if a service exists.
Properties
  • readonlyenabledboolean

    Check if reflection is enabled.

Methods
listServices(): Promise<ServiceInfo[]>

List all available services on the server.

getServiceInfo(serviceName: string): Promise<ServiceDetail>

Get detailed information about a specific service.

Parameters
  • serviceNamestring
    • Fully qualified service name (e.g., "echo.EchoService")
listMethods(serviceName: string): Promise<MethodInfo[]>

Get methods for a specific service.

Parameters
  • serviceNamestring
    • Fully qualified service name
hasService(serviceName: string): Promise<boolean>

Check if a service exists.

Parameters
  • serviceNamestring
    • Fully qualified service name
interface

#ServiceDetail

interface ServiceDetail

Detailed service information.

NameDescription
nameService name
fullNameFully qualified service name
packageNamePackage name
protoFileProto file name
methodsAll methods
Properties
  • readonlynamestring

    Service name

  • readonlyfullNamestring

    Fully qualified service name

  • readonlypackageNamestring

    Package name

  • readonlyprotoFilestring

    Proto file name

  • readonlymethodsreadonly MethodInfo[]

    All methods

interface

#ServiceInfo

interface ServiceInfo

Service information from reflection.

NameDescription
nameFully qualified service name (e.g., "echo.EchoService")
fileProto file name
Properties
  • readonlynamestring

    Fully qualified service name (e.g., "echo.EchoService")

  • readonlyfilestring

    Proto file name

interface

#TlsConfig

interface TlsConfig

TLS configuration for ConnectRPC connections.

NameDescription
rootCertsRoot CA certificate (PEM format).
clientCertClient certificate (PEM format).
clientKeyClient private key (PEM format).
insecureSkip server certificate verification (use only for testing).
Properties
  • readonlyrootCerts?Uint8Array

    Root CA certificate (PEM format).

  • readonlyclientCert?Uint8Array

    Client certificate (PEM format).

  • readonlyclientKey?Uint8Array

    Client private key (PEM format).

  • readonlyinsecure?boolean

    Skip server certificate verification (use only for testing).

Functions

function

#createGrpcClient

function createGrpcClient(config: GrpcClientConfig): ConnectRpcClient

Create a new gRPC client instance.

This is a thin wrapper around createConnectRpcClient with protocol: "grpc" fixed. The client provides Server Reflection support for runtime service discovery.

Parameters
Returns

ConnectRpcClient — A new gRPC client instance

Examples

Basic usage with reflection

import { createGrpcClient } from "@probitas/client-grpc";

const client = createGrpcClient({
  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

import { createGrpcClient } from "@probitas/client-grpc";

const client = createGrpcClient({
  url: "http://localhost:50051",
});

// Discover available services
const services = await client.reflection.listServices();
console.log("Available services:", services);

// Get method information
const info = await client.reflection.getServiceInfo("echo.EchoService");
console.log("Methods:", info.methods);

await client.close();

Testing error responses

import { createGrpcClient } from "@probitas/client-grpc";

const client = createGrpcClient({ url: "http://localhost:50051" });

const response = await client.call(
  "user.UserService",
  "getUser",
  { id: "non-existent" },
  { throwOnError: false }
);

if (!response.ok) {
  console.log("Error code:", response.statusCode);  // NOT_FOUND = 5
}

await client.close();

Using await using for automatic cleanup

import { createGrpcClient } from "@probitas/client-grpc";

await using client = createGrpcClient({
  url: "http://localhost:50051",
});

const res = await client.call("echo.EchoService", "echo", { message: "test" });
console.log(res.data);
// Client automatically closed when scope exits
function

#getGrpcStatusName

function getGrpcStatusName(code: ConnectRpcStatusCode): string

Get the name of a ConnectRPC/gRPC status code.

Parameters
Examples
getStatusName(0);  // "OK"
getStatusName(5);  // "NOT_FOUND"
getStatusName(16); // "UNAUTHENTICATED"
function

#isGrpcStatusCode

function isGrpcStatusCode(code: number): code is ConnectRpcStatusCode

Check if a number is a valid ConnectRPC/gRPC status code.

Parameters
  • codenumber
Examples
isConnectRpcStatusCode(0);   // true
isConnectRpcStatusCode(16);  // true
isConnectRpcStatusCode(99);  // false

Types

type

#FileDescriptorSet

type FileDescriptorSet = MessageShape<FileDescriptorSetSchema>

FileDescriptorSet message type from @bufbuild/protobuf. This is the decoded protobuf message containing file descriptors.

type

#GrpcResponse

type GrpcResponse<T = any> = ConnectRpcResponseSuccess<T>
  | ConnectRpcResponseError<T>
  | ConnectRpcResponseFailure<T>

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
type

#GrpcStatusCode

type GrpcStatusCode = unknown

ConnectRPC/gRPC status code type. Derived from ConnectRpcStatus values.

Variables

const

#GrpcStatus

const GrpcStatus: {
  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.

Search Documentation