Skip to content

Commit

Permalink
fix(ts_proto_library): propagate transitive npm deps (#658)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbedard authored Jul 23, 2024
1 parent 0e2a8ee commit 1e74685
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 38 deletions.
3 changes: 2 additions & 1 deletion docs/proto.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Future work
## ts_proto_library

<pre>
ts_proto_library(<a href="#ts_proto_library-name">name</a>, <a href="#ts_proto_library-node_modules">node_modules</a>, <a href="#ts_proto_library-gen_connect_es">gen_connect_es</a>, <a href="#ts_proto_library-gen_connect_query">gen_connect_query</a>,
ts_proto_library(<a href="#ts_proto_library-name">name</a>, <a href="#ts_proto_library-node_modules">node_modules</a>, <a href="#ts_proto_library-proto">proto</a>, <a href="#ts_proto_library-gen_connect_es">gen_connect_es</a>, <a href="#ts_proto_library-gen_connect_query">gen_connect_query</a>,
<a href="#ts_proto_library-gen_connect_query_service_mapping">gen_connect_query_service_mapping</a>, <a href="#ts_proto_library-copy_files">copy_files</a>, <a href="#ts_proto_library-proto_srcs">proto_srcs</a>, <a href="#ts_proto_library-files_to_copy">files_to_copy</a>, <a href="#ts_proto_library-kwargs">kwargs</a>)
</pre>

Expand All @@ -60,6 +60,7 @@ A macro to generate JavaScript code and TypeScript typings from .proto files.
| :------------- | :------------- | :------------- |
| <a id="ts_proto_library-name"></a>name | name of resulting ts_proto_library target | none |
| <a id="ts_proto_library-node_modules"></a>node_modules | Label pointing to the linked node_modules target where @bufbuild/protoc-gen-es is linked, e.g. //:node_modules. Since the generated code depends on @bufbuild/protobuf, this package must also be linked. If `gen_connect_es = True` then @bufbuild/proto-gen-connect-es should be linked as well. If `gen_connect_query = True` then @bufbuild/proto-gen-connect-query should be linked as well. | none |
| <a id="ts_proto_library-proto"></a>proto | the `proto_library` target that contains the .proto files to generate code for. | none |
| <a id="ts_proto_library-gen_connect_es"></a>gen_connect_es | whether protoc_gen_connect_es should generate grpc services, and therefore `*_connect.{js,d.ts}` should be written. | `True` |
| <a id="ts_proto_library-gen_connect_query"></a>gen_connect_query | whether protoc_gen_connect_query should generate [TanStack Query](https://tanstack.com/query) clients, and therefore `*_connectquery.{js,d.ts}` should be written. | `False` |
| <a id="ts_proto_library-gen_connect_query_service_mapping"></a>gen_connect_query_service_mapping | mapping from source proto file to the named RPC services that file contains. Needed to predict which files will be generated by gen_connect_query. See https://github.com/connectrpc/connect-query-es/tree/main/examples/react/basic/src/gen<br><br>For example, given `a.proto` which contains a service `Foo` and `b.proto` that contains a service `Bar`, the mapping would be `{"a.proto": ["Foo"], "b.proto": ["Bar"]}` | `{}` |
Expand Down
5 changes: 4 additions & 1 deletion examples/proto_grpc/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { LogMessage } from './logger_pb.js'

const msg = LogMessage.fromJson({ message: 'hello world' })
let msg = LogMessage.fromJson({ message: 'hello world' })

// Reference the inherited `.toBinary()` to ensure types from transitive types are included.
msg = LogMessage.fromBinary(msg.toBinary())

console.log(JSON.stringify(msg))
4 changes: 3 additions & 1 deletion examples/proto_grpc/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"compilerOptions": {
"module": "ES2022"
"module": "ES2022",
"moduleResolution": "node",
"lib": ["ES2022", "dom"]
},
// Workaround https://github.com/microsoft/TypeScript/issues/59036
"exclude": []
Expand Down
31 changes: 1 addition & 30 deletions ts/private/ts_proto_library.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"Private implementation details for ts_proto_library"

load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "COPY_FILE_TO_BIN_TOOLCHAINS")
load("@aspect_rules_js//js:libs.bzl", "js_lib_helpers")
load("@aspect_rules_js//js:providers.bzl", "JsInfo", "js_info")
load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common")
load("@rules_proto//proto:proto_common.bzl", proto_toolchains = "toolchains")

Expand Down Expand Up @@ -81,42 +79,15 @@ def _ts_proto_library_impl(ctx):

_protoc_action(ctx, info, js_outs + dts_outs)

direct_srcs = depset(js_outs)
direct_decls = depset(dts_outs)

return [
DefaultInfo(
files = direct_srcs,
runfiles = js_lib_helpers.gather_runfiles(
ctx = ctx,
sources = direct_srcs,
data = [],
deps = ctx.attr.deps,
),
),
OutputGroupInfo(types = direct_decls),
js_info(
target = ctx.label,
types = direct_decls,
sources = direct_srcs,
transitive_types = js_lib_helpers.gather_transitive_types(
types = dts_outs,
targets = ctx.attr.deps,
),
transitive_sources = js_lib_helpers.gather_transitive_sources(
sources = js_outs,
targets = ctx.attr.deps,
),
files = depset(js_outs + dts_outs),
),
]

ts_proto_library = rule(
implementation = _ts_proto_library_impl,
attrs = dict({
"deps": attr.label_list(
providers = [JsInfo],
doc = "Other ts_proto_library rules. TODO: could we collect them with an aspect",
),
"gen_connect_es": attr.bool(
doc = "whether to generate service stubs with gen-connect-es",
default = True,
Expand Down
19 changes: 14 additions & 5 deletions ts/proto.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ Future work
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")
load("@aspect_bazel_lib//lib:directory_path.bzl", "directory_path", "make_directory_path")
load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files")
load("@aspect_rules_js//js:defs.bzl", "js_binary")
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_library")
load("//ts/private:ts_proto_library.bzl", ts_proto_library_rule = "ts_proto_library")

def ts_proto_library(name, node_modules, gen_connect_es = True, gen_connect_query = False, gen_connect_query_service_mapping = {}, copy_files = True, proto_srcs = None, files_to_copy = None, **kwargs):
def ts_proto_library(name, node_modules, proto, gen_connect_es = True, gen_connect_query = False, gen_connect_query_service_mapping = {}, copy_files = True, proto_srcs = None, files_to_copy = None, **kwargs):
"""
A macro to generate JavaScript code and TypeScript typings from .proto files.
Expand All @@ -57,6 +57,7 @@ def ts_proto_library(name, node_modules, gen_connect_es = True, gen_connect_quer
Since the generated code depends on @bufbuild/protobuf, this package must also be linked.
If `gen_connect_es = True` then @bufbuild/proto-gen-connect-es should be linked as well.
If `gen_connect_query = True` then @bufbuild/proto-gen-connect-query should be linked as well.
proto: the `proto_library` target that contains the .proto files to generate code for.
gen_connect_es: whether protoc_gen_connect_es should generate grpc services, and therefore `*_connect.{js,d.ts}` should be written.
gen_connect_query: whether protoc_gen_connect_query should generate [TanStack Query](https://tanstack.com/query) clients, and therefore `*_connectquery.{js,d.ts}` should be written.
gen_connect_query_service_mapping: mapping from source proto file to the named RPC services that file contains.
Expand Down Expand Up @@ -121,16 +122,24 @@ def ts_proto_library(name, node_modules, gen_connect_es = True, gen_connect_quer
entry_point = protoc_gen_connect_query_entry,
)

protoc_target = "_{}_protoc".format(name)
ts_proto_library_rule(
name = name,
name = protoc_target,
protoc_gen_es = protoc_gen_es_target,
protoc_gen_connect_es = protoc_gen_connect_es_target,
protoc_gen_connect_query = protoc_gen_connect_query_target,
# The codegen always has a runtime dependency on the protobuf runtime
deps = kwargs.pop("deps", []) + [node_modules + "/@bufbuild/protobuf"],
gen_connect_es = gen_connect_es,
gen_connect_query = gen_connect_query,
gen_connect_query_service_mapping = gen_connect_query_service_mapping,
proto = proto,
)

js_library(
name = name,
srcs = [":{}".format(protoc_target)],
# The codegen always has a runtime dependency on the protobuf runtime
# TODO: could we collect them with an aspect?
deps = kwargs.pop("deps", []) + [node_modules + "/@bufbuild/protobuf"],
**kwargs
)

Expand Down

0 comments on commit 1e74685

Please sign in to comment.