Skip to content

Commit 4c6c237

Browse files
authored
Use ts_grpc_compile macro to compile NodeJS TS/JS proto files (#95)
## What is the goal of this PR? Currently, the developer experience of compiling `@graknlabs_protocol` for NodeJS is suboptimal: we have to maintain a list of raw proto files in `//protocol:proto-raw-buffers` and it's generally inconsistent with how we compile protos in other languages (Python/Java) ## What are the changes implemented in this PR? Implement `ts_grpc_compile` macro which `//grpc/nodejs:protocol` will now utilize
1 parent 410a3b5 commit 4c6c237

File tree

2 files changed

+143
-46
lines changed

2 files changed

+143
-46
lines changed

grpc/nodejs/BUILD

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm", "nodejs_binary")
2121
load("@graknlabs_bazel_distribution//npm:rules.bzl", "assemble_npm", "deploy_npm")
2222
load("@graknlabs_dependencies//distribution:deployment.bzl", "deployment")
2323
load("//:deployment.bzl", github_deployment = "deployment")
24+
load("//grpc/nodejs:rules.bzl", "ts_grpc_compile")
2425

2526

2627
nodejs_binary(
@@ -37,54 +38,21 @@ nodejs_binary(
3738
templated_args = ["--nobazel_node_patches"],
3839
)
3940

40-
41-
genrule(
41+
ts_grpc_compile(
4242
name = "protocol",
43-
outs = [
44-
"protobuf/answer_pb.d.ts",
45-
"protobuf/answer_pb.js",
46-
"protobuf/concept_pb.d.ts",
47-
"protobuf/concept_pb.js",
48-
"protobuf/database_pb.d.ts",
49-
"protobuf/database_pb.js",
50-
"protobuf/grakn_pb.d.ts",
51-
"protobuf/grakn_pb.js",
52-
"protobuf/grakn_grpc_pb.d.ts",
53-
"protobuf/grakn_grpc_pb.js",
54-
"protobuf/logic_pb.d.ts",
55-
"protobuf/logic_pb.js",
56-
"protobuf/options_pb.d.ts",
57-
"protobuf/options_pb.js",
58-
"protobuf/query_pb.d.ts",
59-
"protobuf/query_pb.js",
60-
"protobuf/session_pb.d.ts",
61-
"protobuf/session_pb.js",
62-
"protobuf/transaction_pb.d.ts",
63-
"protobuf/transaction_pb.js",
64-
],
65-
# The below command performs a protoc compilation of our proto files into typescript and javascript. Line by line:
66-
# Run the node.js protoc (protocol compiler) with the following flags:
67-
# Use the gen-ts plugin to generate typescript declaration files in addition to javascript
68-
# Output javascript with commonjs style exports, to the genrule output directory.
69-
# Output services to the genrule output directory (without this line, grakn_grpc_pb is omitted)
70-
# Output typescript to (you guessed it) the genrule output directory
71-
# Set the .proto file relative path to root folder (same as where WORKSPACE resides)
72-
# Use the .proto files found in the :proto-raw-buffers filegroup as inputs.
73-
cmd = "$(execpath //grpc/nodejs:grpc_tools_node_protoc) \
74-
--plugin='protoc-gen-ts=$(rootpath @npm//:node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts)' \
75-
--js_out='import_style=commonjs,binary:./$(@D)/' \
76-
--grpc_out='grpc_js:./$(@D)/' \
77-
--ts_out='grpc_js:./$(@D)/' \
78-
--proto_path=. \
79-
$(execpaths //protobuf:proto-raw-buffers);",
80-
tools = [
81-
"//grpc/nodejs:grpc_tools_node_protoc",
82-
"@npm//:node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts",
83-
"@npm//grpc_tools_node_protoc_ts",
84-
"@npm//google-protobuf",
43+
deps = [
44+
"//protobuf:answer-proto",
45+
"//protobuf:concept-proto",
46+
"//protobuf:database-proto",
47+
"//protobuf:grakn-proto",
48+
"//protobuf:logic-proto",
49+
"//protobuf:options-proto",
50+
"//protobuf:query-proto",
51+
"//protobuf:session-proto",
52+
"//protobuf:transaction-proto",
8553
],
86-
srcs = [
87-
"//protobuf:proto-raw-buffers",
54+
grpc_deps = [
55+
"//protobuf:grakn-proto",
8856
]
8957
)
9058

grpc/nodejs/rules.bzl

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#
2+
# Copyright (C) 2020 Grakn Labs
3+
#
4+
# This program is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU Affero General Public License as
6+
# published by the Free Software Foundation, either version 3 of the
7+
# License, or (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU Affero General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU Affero General Public License
15+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
#
17+
18+
def _proto_sources(ctx):
19+
inputs = []
20+
for dep in ctx.attr.deps:
21+
for src in dep[ProtoInfo].direct_sources:
22+
inputs.append(src)
23+
return DefaultInfo(files = depset(inputs))
24+
25+
26+
def _unpack_proto_archive(ctx):
27+
outputs = []
28+
for dep in ctx.attr.deps:
29+
for src in dep[ProtoInfo].direct_sources:
30+
outputs.extend([
31+
ctx.actions.declare_file(
32+
src.path.replace('.proto', '_pb.d.ts')
33+
),
34+
ctx.actions.declare_file(
35+
src.path.replace('.proto', '_pb.js')
36+
),
37+
])
38+
39+
for dep in ctx.attr.grpc_deps:
40+
for src in dep[ProtoInfo].direct_sources:
41+
outputs.extend([
42+
ctx.actions.declare_file(
43+
src.path.replace('.proto', '_grpc_pb.js')
44+
),
45+
ctx.actions.declare_file(
46+
src.path.replace('.proto', '_grpc_pb.d.ts')
47+
),
48+
])
49+
ctx.actions.run_shell(
50+
inputs = [ctx.file.archive],
51+
outputs = outputs,
52+
mnemonic='x',
53+
command = "mkdir -p {} && tar -xvf {} -C {}/{}".format(
54+
ctx.label.package, ctx.file.archive.path,
55+
ctx.var["BINDIR"], ctx.label.package
56+
)
57+
)
58+
return DefaultInfo(files = depset(outputs))
59+
60+
61+
proto_sources = rule(
62+
attrs = {
63+
"deps": attr.label_list(
64+
providers = [ProtoInfo],
65+
)
66+
},
67+
implementation = _proto_sources
68+
)
69+
70+
unpack_proto_archive = rule(
71+
attrs = {
72+
"deps": attr.label_list(
73+
providers = [ProtoInfo],
74+
),
75+
"grpc_deps": attr.label_list(
76+
providers = [ProtoInfo],
77+
),
78+
"archive": attr.label(
79+
allow_single_file = True
80+
),
81+
},
82+
implementation = _unpack_proto_archive
83+
)
84+
85+
86+
def ts_grpc_compile(
87+
name,
88+
deps,
89+
grpc_deps):
90+
proto_sources_name = "{}__do_not_reference_1".format(name)
91+
genrule_name = "{}__do_not_reference_2".format(name)
92+
proto_sources(
93+
name = proto_sources_name,
94+
deps = deps
95+
)
96+
native.genrule(
97+
name = genrule_name,
98+
outs = [
99+
"{}.tar.gz".format(genrule_name),
100+
],
101+
# The below command performs a protoc compilation of our proto files into typescript and javascript. Line by line:
102+
# Run the node.js protoc (protocol compiler) with the following flags:
103+
# Use the gen-ts plugin to generate typescript declaration files in addition to javascript
104+
# Output javascript with commonjs style exports, to the genrule output directory.
105+
# Output services to the genrule output directory (without this line, grakn_grpc_pb is omitted)
106+
# Output typescript to (you guessed it) the genrule output directory
107+
# Set the .proto file relative path to root folder (same as where WORKSPACE resides)
108+
# Use the .proto files found in the :proto-raw-buffers filegroup as inputs.
109+
cmd = "$(execpath //grpc/nodejs:grpc_tools_node_protoc) \
110+
--plugin='protoc-gen-ts=$(rootpath @npm//:node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts)' \
111+
--js_out='import_style=commonjs,binary:./$(@D)/' \
112+
--grpc_out='grpc_js:./$(@D)/' \
113+
--ts_out='grpc_js:./$(@D)/' \
114+
--proto_path=. \
115+
$(execpaths :{}) && tar cvf $@ -C ./$(@D)/ .".format(proto_sources_name),
116+
tools = [
117+
"//grpc/nodejs:grpc_tools_node_protoc",
118+
"@npm//:node_modules/grpc_tools_node_protoc_ts/bin/protoc-gen-ts",
119+
"@npm//grpc_tools_node_protoc_ts",
120+
"@npm//google-protobuf",
121+
],
122+
srcs = [proto_sources_name]
123+
)
124+
unpack_proto_archive(
125+
name = name,
126+
deps = deps,
127+
grpc_deps = grpc_deps,
128+
archive = genrule_name,
129+
)

0 commit comments

Comments
 (0)