agreatfool/grpc_tools_node_protoc_ts

Include modules in geneartion

Closed this issue · 6 comments

I'm trying to generate some TS files from proto that has a proto dependency on another repo that has it's own node module.

This is my setup:

Repo A (node module a_protos)
protos/
A.proto

Repo B (imports a_protos)
protos/
B.proto

In that setup B.proto includes a file in A.proto. I run the following protoc command

protoc --ts_out=./src --plugin=protoc-gen-ts=`which protoc-gen-ts` -I protos -I ../a/protos protos/*.proto

I get a B_pb.d.ts that has an import assuming ./A_pb.d.ts. The import should be to a_protos modules. If I replace it by hand then everything compiles correct. Is there a way to generate protos in Repo B where they automatically include the module import?

I made a test. Make a file examples/proto/test.proto:

a

syntax = "proto3";

package com.test;

import "book.proto";

message TestStore {
    repeated com.book.Book book = 1;
}

message GetStoreRequest {
    int64 id = 1;
}

service TestService {
    rpc GetStore (GetStoreRequest) returns (TestStore) {}
}

Then run the script: examples/bash/build.sh. Seems generated codes are all ok.

test_pb.d.ts:

import * as book_pb from "./book_pb";

export class TestStore extends jspb.Message { 
    clearBookList(): void;
    getBookList(): Array<book_pb.Book>;
    setBookList(value: Array<book_pb.Book>): TestStore;
    addBook(value?: book_pb.Book, index?: number): book_pb.Book;

    // ...
}

So if proto files are all put in the same dir, it works. How's your proto files positions?

Thanks for the example but it doesn't quite match my setup. For me book.proto would be in another repo and would be exported in a node module called books. Ideally this is what I would want my generated test_pb.d.ts to look like.

import * as book_pb from "books";

export class TestStore extends jspb.Message { 
    clearBookList(): void;
    getBookList(): Array<book_pb.Book>;
    setBookList(value: Array<book_pb.Book>): TestStore;
    addBook(value?: book_pb.Book, index?: number): book_pb.Book;

    // ...
}

Also node/typescript is not a language I'm very strong in. I'm trying to make a client module for a node program to talk to a Go grpc server.

As I know, protobuf using protoc -I $dir to search proto files.

So, solution could be:

a

protoc -I ./project_root/src/proto -I ./project_root/node_modules/some_module/proto

Yeah you're right. Sorry I don't think my problem was clear. I've included a zip with the project structure I'm trying to replicate. Where books and test would be their own repos.

node_proto_example.zip

My oder of operations would be to do the following:

cd books
npm run protoc
npm run build

cd ../test
npm install ../books
npm run protoc
npm run grpc

I want the import statement in test/src/test_pb.d.ts to be

import * as books_pb from 'books';

but it's generated as

import * as books_pb from "./books_pb";

I'm looking for a way to run the generation command to generate test_pb.d.ts with the import statement referencing the module library that contains books_pb.d.ts. I don't want test module to have its own copy of it.

Like I said typescript/node is not my strong point so I might be misunderstanding how this tool is suppose to be used.

Thanks for the help on this by the way.

Your understanding is correct. I got your idea.

You want a module book. Contains book.proto with all generated codes of this proto file. And you want a project test, has it's own proto file and it's own generated codes. And the proto & codes of this project depends on the proto & codes of module book.

I think you could use some tools to implement this:

  • Using npm hook to generate codes from proto file of book module, and put generated codes to the same dir of your test codes
  • Using .gitignore to ignore the generated codes from the proto file of book module. You the better also ignore the generated codes of your own project, they are all good to be generated in CI system, or your deploying scripts. Don't put them into git.

Like:

project_root /
                        | proto /
                        |            | test.proto
                        | generated /
                        |                      | test_pb.d.ts (generated from your CI or deploying scripts, ignored in .gitignore)
                        |                      | book_pb.d.ts (generated from your CI or deploying scripts, ignored in .gitignore)
                        | node_modules /
                        |                              | module_book /
                        |                              |                            | proto /
                        |                              |                            |            | book.proto

I'd prefer leaving grpc_tools_node_protoc_ts simple. Using some outside tools or scripts to implement requirements.

@agreatfool Thanks for the suggestions, really appreciate the help. I totally understand keeping the tool simple I was hoping there was some undocumented flag or something I could have utilized. No worries I'll investigate what you suggested.