UNPKG

@azure/functions-extensions-servicebus

Version:
88 lines (77 loc) 3.71 kB
// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. import * as grpc from '@grpc/grpc-js'; import * as protoLoader from '@grpc/proto-loader'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { SETTLEMENT_PROTO_CONTENT } from './constants/settlementProtoConstant'; // Cache for the loaded package definition to avoid repeated parsing let cachedPackageDefinition: grpc.GrpcObject | null = null; /** * Creates and returns a gRPC client for the Settlement service using embedded proto definition. * This approach completely eliminates the need for external .proto files by creating a temporary * proto file from the embedded content, loading it, and then cleaning up. * * @template T - The type of gRPC client to create, extends grpc.Client * * @param options - The configuration options for creating the gRPC client * @param options.serviceName - Name of the service in the proto definition * @param options.address - The server address to connect to (e.g., "localhost:50051") * @param options.credentials - gRPC channel credentials to use for secure communication (defaults to insecure) * @param options.grpcMaxMessageLength - Maximum message length in bytes for both sending and receiving gRPC messages * * @returns A new instance of the specified gRPC client */ export function createGrpcClient<T extends grpc.Client = grpc.Client>({ serviceName, address, credentials = grpc.credentials.createInsecure(), grpcMaxMessageLength, }: { serviceName: string; address: string; credentials?: grpc.ChannelCredentials; grpcMaxMessageLength: number; }): T { // Load the embedded proto definition if not already cached if (!cachedPackageDefinition) { // Create a temporary proto file from the embedded content const tempDir = os.tmpdir(); const tempProtoFile = path.join(tempDir, `settlement.proto`); try { // Write the proto content to a temporary file fs.writeFileSync(tempProtoFile, SETTLEMENT_PROTO_CONTENT); // Load the proto definition from the temporary file const packageDefinition = protoLoader.loadSync(tempProtoFile, { keepCase: false, longs: String, enums: String, defaults: true, oneofs: true, includeDirs: [tempDir], }); cachedPackageDefinition = grpc.loadPackageDefinition(packageDefinition); } finally { // Clean up the temporary file try { fs.unlinkSync(tempProtoFile); } catch { // Ignore cleanup errors } } } // Retrieve the service client constructor from the loaded gRPC object // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access const ServiceClientConstructor = (cachedPackageDefinition as any)[serviceName] as grpc.ServiceClientConstructor; // Throw an error if the service is not found if (!ServiceClientConstructor) { throw new Error(`Service "${serviceName}" not found in embedded proto definition`); } const clientOptions: grpc.ChannelOptions = { 'grpc.max_send_message_length': grpcMaxMessageLength, 'grpc.max_receive_message_length': grpcMaxMessageLength, }; // Create and return a new instance of the service client return new ServiceClientConstructor(address, credentials, clientOptions) as unknown as T; }