Search code examples
protocol-buffersgrpcgrpc-node

nodejs grpc-tools generate js code protobuf package import path is error


this is my project:

/nodejs
    /out
    /protos
        project.proto
    package.json 

project.proto

syntax = "proto3";

package com.test;

import "google/protobuf/timestamp.proto";
import "google/protobuf/descriptor.proto";
import "google/type/date.proto";

import "google/protobuf/empty.proto";
import "google/protobuf/wrappers.proto";

option java_outer_classname = "Message";
option java_package = "com.test";

message ProjectMessage {

    string id = 1;

    google.protobuf.Timestamp due_date = 2;

    google.protobuf.BoolValue created_by_own_wallet = 3;

    google.type.Date date_of_loss = 4;

}

service ProjectService {
    rpc get(google.protobuf.StringValue) returns (ProjectMessage) {};
}

package.json

{
    "name": "grpc-api",
    "version": "1.0.0",
    "description": "proto api",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "grpc": "grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./out --grpc_out=grpc_js:./out -I=./node_modules/google-proto-files -I=./protos ./protos/*.proto"
    },
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@grpc/grpc-js": "^1.8.17",
        "google-proto-files": "^2.5.0",
        "grpc-tools": "^1.12.4"
    }
}

when i run npm run grpc will create project_grpc_pb.js and project_pb.js, but the file is error path import of google.type.Date, it resolve as relative path: ./google/type/date_pb.js

this is a example of my project_grpc_pb.js:

// GENERATED CODE -- DO NOT EDIT!

'use strict';
var grpc = require('@grpc/grpc-js');
var project_pb = require('./project_pb.js');
var google_protobuf_timestamp_pb = require('google-protobuf/google/protobuf/timestamp_pb.js');
var google_protobuf_descriptor_pb = require('google-protobuf/google/protobuf/descriptor_pb.js');
// This require path is error
var google_type_date_pb = require('./google/type/date_pb.js');
var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js');
var google_protobuf_wrappers_pb = require('google-protobuf/google/protobuf/wrappers_pb.js');

function serialize_com_test_ProjectMessage(arg) {
    if (!(arg instanceof project_pb.ProjectMessage)) {
      throw new Error('Expected argument of type com.test.ProjectMessage');
    }
    return Buffer.from(arg.serializeBinary());
}

function deserialize_com_test_ProjectMessage(buffer_arg) {
    return project_pb.ProjectMessage.deserializeBinary(new Uint8Array(buffer_arg));
}

function serialize_google_protobuf_StringValue(arg) {
    if (!(arg instanceof google_protobuf_wrappers_pb.StringValue)) {
      throw new Error('Expected argument of type google.protobuf.StringValue');
    }
    return Buffer.from(arg.serializeBinary());
}

function deserialize_google_protobuf_StringValue(buffer_arg) {
    return google_protobuf_wrappers_pb.StringValue.deserializeBinary(new Uint8Array(buffer_arg));
}


var ProjectServiceService = exports.ProjectServiceService = {
    get: {
      path: '/com.test.ProjectService/get',
      requestStream: false,
      responseStream: false,
      requestType: google_protobuf_wrappers_pb.StringValue,
      responseType: project_pb.ProjectMessage,
      requestSerialize: serialize_google_protobuf_StringValue,
      requestDeserialize: deserialize_google_protobuf_StringValue,
      responseSerialize: serialize_com_test_ProjectMessage,
      responseDeserialize: deserialize_com_test_ProjectMessage,
    },
};

exports.ProjectServiceClient = grpc.makeGenericClientConstructor(ProjectServiceService);

I dont know how to resolve this problem.


Solution

  • Try appending date.proto to your protoc compile:

    grpc_tools_node_protoc \
    --js_out=import_style=commonjs,binary:${PWD}/out \
    --grpc_out=grpc_js:${PWD}/out \
    --proto_path=${PWD}/node_modules/google-proto-files \
    --proto_path=${PWD}/protos \
    ${PWD}/protos/project.proto \
    ${PWD}/node_modules/google-proto-files/google/type/date.proto
    

    Yields: out:

    out
    ├── google
    │   └── type
    │       ├── date_grpc_pb.js
    │       └── date_pb.js
    ├── project_grpc_pb.js
    └── project_pb.js
    

    If you'd prefer (and you likely should) to restructure out so that there's a specific google directory, you could simply do two protoc steps and direct the output differently and then you'd be able to require the generated Google type(s) more cleanly.