import * as grpc from "grpc"; import merge from 'lodash.merge'; import { CallOptions, Metadata } from "grpc"; import { ClientConstructor, Pool, PoolOptions } from "./pool"; import { GrpcRequest } from "./request"; type CallClientOption = CallOptions & { metadata?: Metadata }; export interface ClientDefaults { callOptions: CallClientOption clientOptions: PoolOptions } export class Client { protected static defaults: ClientDefaults = { callOptions: {}, clientOptions: { address: "", credentials: grpc.credentials.createInsecure(), size: 1, }, }; pool: Pool; constructor( private readonly _client: Pool | ClientConstructor, private readonly options?: PoolOptions ) { this.pool = this.initPool(_client); } static create( _client: Pool | ClientConstructor, options?: PoolOptions ): Client { return new Client(_client, options); } static getClientDefaults() { return Client.defaults.clientOptions } static getCallDefaults() { return Client.defaults.callOptions } static setClientDefaults(defaults: Partial) { Client.defaults.clientOptions = merge(Client.defaults.clientOptions, defaults) } static setCallDefaults(defaults: Partial) { Client.defaults.callOptions = merge(Client.defaults.callOptions, defaults) } newClient() { const constructor = this.constructor as new (_client: Pool | ClientConstructor, options?: PoolOptions) => Client return new constructor(this._client, this.options); } get client() { return this.pool.get(); } clientOptions() { return merge(Client.defaults.clientOptions, this.options) } callOptions() { return Client.defaults.callOptions } protected initPool(client: Pool | ClientConstructor): Pool { if (client instanceof Pool) { return client; } else { return new Pool(client, this.clientOptions()); } } request() { const defaultCallOptions = this.callOptions() || {}; return GrpcRequest.create( this.pool.get(), defaultCallOptions.metadata, defaultCallOptions, ); } }