0

这是src我的项目目录的结构:

.
├── config.ts
├── protos
│   ├── index.proto
│   ├── index.ts
│   ├── share
│   │   ├── topic.proto
│   │   ├── topic_pb.d.ts
│   │   ├── user.proto
│   │   └── user_pb.d.ts
│   ├── topic
│   │   ├── service.proto
│   │   ├── service_grpc_pb.d.ts
│   │   ├── service_pb.d.ts
│   │   ├── topic.integration.test.ts
│   │   ├── topic.proto
│   │   ├── topicServiceImpl.ts
│   │   ├── topicServiceImplDynamic.ts
│   │   └── topic_pb.d.ts
│   └── user
│       ├── service.proto
│       ├── service_grpc_pb.d.ts
│       ├── service_pb.d.ts
│       ├── user.proto
│       ├── userServiceImpl.ts
│       └── user_pb.d.ts
└── server.ts

share/user.proto

syntax = "proto3";

package share;

message UserBase {
  string loginname = 1;
  string avatar_url = 2;
}

topic/topic.proto

syntax = "proto3";

package topic;

import "share/user.proto";

enum Tab {
  share = 0;
  ask = 1;
  good = 2;
  job = 3;
}

message Topic {
  string id = 1;
  string author_id = 2;
  Tab tab = 3;
  string title = 4;
  string content = 5;
  share.UserBase author = 6;
  bool good = 7;
  bool top = 8;
  int32 reply_count = 9;
  int32 visit_count = 10;
  string create_at = 11;
  string last_reply_at = 12;
}

如您所见,我尝试导入share包并UserBase在消息类型中使用消息Topic类型。当我尝试启动服务器时,出现错误:

Type .topic.Topic 中没有这样的 Type 或 Enum 'share.UserBase'

但是当我将包导入路径更改为相对路径时import "../share/user.proto";。它工作正常并获得服务器日志:Server is listening on http://localhost:3000.

以上是动态codegen的用法。

现在,我切换到使用静态代码生成,这是生成代码的 shell 脚本:

protoc \
  --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts \
  --ts_out=./src/protos \
  -I ./src/protos \
  ./src/protos/**/*.proto

似乎协议缓冲区编译器不支持相对路径,出现错误:

../share/user.proto: Backslashes, consecutive slashes, ".", or ".." are not allowed in the virtual path

而且,我将包导入路径改回import "share/user.proto";. 它正确生成了代码,但是当我尝试启动服务器时,出现了同样的错误:

Type .topic.Topic 中没有这样的 Type 或 Enum 'share.UserBase'

有点奇怪。

软件包版本:

"grpc-tools": "^1.6.6",
"grpc_tools_node_protoc_ts": "^4.1.3",
protoc --version                                                                  
libprotoc 3.10.0

更新:

回购:https ://github.com/mrdulin/nodejs-grpc/tree/master/src

4

1 回答 1

1

您的动态代码生成失败,因为您没有指定搜索导入.proto文件的路径。您可以includeDirs在调用时使用该选项来执行此操作protoLoader.loadSync,它的工作方式与-I您传递给的选项非常相似protoc。在这种情况下,您正在从src/protos目录加载 proto 文件,因此传递 option 就足够了includeDirs: [__dirname]。然后文件中的导入路径.proto应该相对于该目录,就像您使用protoc.

当您尝试使用静态代码生成时,您可能会看到相同的错误,因为它实际上是动态代码生成错误;尝试使用静态生成的代码时,您似乎没有删除动态代码生成代码。

但是,静态生成的代码将面临的主要问题是您只生成 TypeScript 类型定义文件。您还需要生成 JavaScript 文件才能实际运行它。官方的 Node gRPC 插件在包proto中分发。grpc-tools它带有一个名为 的二进制文件grpc_tools_node_protoc,它应该用来代替protoc插件并自动包含插件。您仍然需要传递一个--js_out标志来生成该代码。

于 2020-08-25T04:00:51.457 回答