Skip to content
Documentation
Handle Proto

Handle Proto

Sometimes, we need the capability to handle proto content, and the gRPCity library provides such functionality, which is also internally invoked.

For example: add(serviceName, implementation) requires obtaining the service name defined in the proto file.

Load proto

Suppose our proto path is protos/test/helloworld/, and the proto content is as follows:

protos/test/helloworld/helloworld.proto
service Greeter {
  // Sends a greeting
  rpc SayHello(model.HelloRequest) returns (model.HelloReply) {}
  rpc SayHello2(model.HelloRequest) returns (model.HelloReply) {}
}

We need to load the proto first.

import { ProtoLoader } from 'grpcity'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
 
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const loader = new ProtoLoader({
    location: path.resolve(__dirname, 'protos'),
    files: ['test/helloworld/helloworld.proto']
})
 
(async () => {
    await loader.init()
})()

Package Prefix

In some scenarios, we need to prefix the package name of the proto. Use the following approach:

await loader.init({
  isDev: true,
  packagePrefix: 'stage.dev'
})

When using packagePrefix, the loaded proto definition will be modified, and all paths will have this prefix.

service(name)

The name parameter refers to the route in the proto file, specifically to the location of the service.

const serviceDefinition = loader.service('test.helloworld.Greeter')
console.log(serviceDefinition)

Prints:

Terminal
{
  SayHello: {
    path: '/stage.dev.test.helloworld.Greeter/SayHello',
    requestStream: false,
    responseStream: false,
    requestSerialize: [Function: serialize],
    requestDeserialize: [Function: deserialize],
    responseSerialize: [Function: serialize],
    responseDeserialize: [Function: deserialize],
    originalName: 'sayHello',
    requestType: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    },
    responseType: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    }
  },
  SayHello2: {
    path: '/stage.dev.test.helloworld.Greeter/SayHello2',
    requestStream: false,
    responseStream: false,
    requestSerialize: [Function: serialize],
    requestDeserialize: [Function: deserialize],
    responseSerialize: [Function: serialize],
    responseDeserialize: [Function: deserialize],
    originalName: 'sayHello2',
    requestType: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    },
    responseType: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    }
  }
}

type(name)

The name parameter specifies the route in the proto file, from the package to the service, model, or message. The capabilities of type() include service().

Example with type('test'):

const typePkg = loader.type('test')
console.log(typePkg)

Prints:

Terminal
{
  helloworld: {
    Greeter: [class ServiceClientImpl extends Client] {
      service: [Object],
      serviceName: 'Greeter'
    },
    Hellor: [class ServiceClientImpl extends Client] {
      service: [Object],
      serviceName: 'Hellor'
    },
    model: { HelloRequest: [Object], HelloReply: [Object] }
  }
}

Example with type('test.helloworld'):

const typePkg = loader.type('test.helloworld')
console.log(typePkg)

Prints:

Terminal
{
  Greeter: [class ServiceClientImpl extends Client] {
    service: { SayHello: [Object], SayHello2: [Object] },
    serviceName: 'Greeter'
  },
  Hellor: [class ServiceClientImpl extends Client] {
    service: { SayHello: [Object], SayHello2: [Object] },
    serviceName: 'Hellor'
  },
  model: {
    HelloRequest: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    },
    HelloReply: {
      format: 'Protocol Buffer 3 DescriptorProto',
      type: [Object],
      fileDescriptorProtos: [Array]
    }
  }
}