import { type Client } from "@connectrpc/connect"; import { Dapr } from "../../../proto/dapr/proto/runtime/v1/dapr_pb"; import IClient from "../../../interfaces/Client/IClient"; import { DaprClientOptions } from "../../../types/DaprClientOptions"; /** * gRPC-based Dapr client implementation. * * Provides low-level gRPC communication with the Dapr sidecar using ConnectRPC transport. * This is the protocol implementation layer; most applications should use DaprClient instead. * * Uses ConnectRPC for efficient binary serialization and streaming support. * Automatically configures connection pooling, max message sizes, and TLS based on configuration. * * @implements {IClient} * @see {@link DaprClient} for the public-facing unified client * @see {@link https://connectrpc.com | ConnectRPC Documentation} * * @internal */ export default class GRPCClient implements IClient { /** * Resolved gRPC client configuration (host, port, protocol, etc.). */ readonly options: DaprClientOptions; /** * Initialization status flag. * * @private */ private isInitialized; /** * ConnectRPC gRPC client for making RPC calls. * * @private */ private readonly client; /** * Logger instance for debug/info/error messages. * * @private */ private readonly logger; /** * Resolved gRPC endpoint (hostname:port with TLS info). * * @private */ private daprEndpoint; /** * Creates a new gRPC Dapr client instance. * * Initializes the ConnectRPC transport with configured endpoint, interceptors for API tokens, * and message size limits. Does not establish connection until start() is called. * * @param options - gRPC client configuration * @param options.daprHost - Sidecar hostname (default: localhost, env: DAPR_HOST) * @param options.daprPort - Sidecar gRPC port (default: 50001, env: DAPR_PORT) * @param options.daprApiToken - API token for authentication (env: DAPR_API_TOKEN) * @param options.isKeepAlive - Enable connection keep-alive (default: true) * @param options.maxBodySizeMb - Max message size in MB (default: 4) * @param options.logger - Custom logger instance * @param options.actor - Actor configuration * * @example * ```typescript * const client = new GRPCClient({ * daprHost: "localhost", * daprPort: "50001", * daprApiToken: "secret-token" * }); * await client.start(); * const grpcClient = await client.getClient(); * ``` */ constructor(options: Partial); /** * Gets the underlying ConnectRPC client for making RPC calls. * * Ensures the client is initialized before returning it. If requiresInitialization is true * and the client is not initialized, calls start() to initialize. * * @param requiresInitialization - Whether to auto-initialize if needed (default: true) * @returns Promise resolving to the initialized ConnectRPC client * * @throws {Error} If initialization fails * * @internal */ getClient(requiresInitialization?: boolean): Promise>; /** * Generates gRPC endpoint from configuration. * * Resolves the sidecar endpoint using provided options, environment variables, * and defaults. Validates endpoint URI format for gRPC connectivity. * * @param options - Client configuration with daprHost/daprPort * @returns Parsed GrpcEndpoint with hostname, port, and TLS info * * @private */ private generateEndpoint; /** * Generates ConnectRPC interceptor for API token authentication. * * Adds the "dapr-api-token" header to all outgoing gRPC requests if a token is configured. * * @returns ConnectRPC interceptor function * * @private */ private generateInterceptor; /** * Sets the initialization status flag. * * @param isInitialized - Whether the client is initialized * * @internal */ setIsInitialized(isInitialized: boolean): void; /** * Gets the current initialization status. * * @returns true if client is initialized, false otherwise * * @internal */ getIsInitialized(): boolean; /** * Closes the gRPC connection (no-op with ConnectRPC transport). * * ConnectRPC manages connections automatically, so explicit closure is not needed. * * @returns Empty promise * * @internal */ stop(): Promise; /** * Waits for the ConnectRPC client to be ready (no-op with ConnectRPC). * * ConnectRPC establishes connections lazily on first request, so explicit wait is not needed. * * @returns Empty promise * * @internal */ _startWaitForClientReady(): Promise; /** * Waits for the Dapr sidecar to become available. * * Polls the sidecar health status until it's ready or timeout is exceeded. * This ensures the sidecar is available before making API calls. * * @returns Promise that resolves when sidecar is ready * * @throws {Error} If sidecar doesn't become ready within timeout * * @internal */ _startAwaitSidecarStarted(): Promise; /** * Initializes the gRPC client for use. * * Waits for the sidecar to become available and ensures client readiness. * Sets the initialized flag after successful startup. * * @returns Promise that resolves when client is initialized * * @throws {Error} If initialization fails * * @internal */ start(): Promise; }