Skip to content

Commit

Permalink
fix: ts_proto_library with strip_import_prefix in proto_library
Browse files Browse the repository at this point in the history
  • Loading branch information
amari committed Jan 10, 2025
1 parent 9700b5e commit ce58380
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 5 deletions.
2 changes: 2 additions & 0 deletions examples/proto_grpc/status_connect.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto

// @generated by protoc-gen-connect-es v1.4.0 with parameter "keep_empty_files=true,target=js+dts"
// @generated from file examples/proto_grpc/status.proto (package rpc, syntax proto3)
/* eslint-disable */
Expand Down
11 changes: 11 additions & 0 deletions examples/proto_grpc/status_pb.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto

// @generated by protoc-gen-es v1.8.0 with parameter "keep_empty_files=true,target=js+dts"
// @generated from file examples/proto_grpc/status.proto (package rpc, syntax proto3)
/* eslint-disable */
Expand All @@ -11,16 +13,25 @@ import { Message, proto3 } from "@bufbuild/protobuf";
*/
export declare class Status extends Message<Status> {
/**
* The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
*
* @generated from field: int32 code = 1;
*/
code: number;

/**
* A developer-facing error message, which should be in English. Any
* user-facing error message should be localized and sent in the
* [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
*
* @generated from field: string message = 2;
*/
message: string;

/**
* A list of messages that carry the error details. There will be a
* common set of message types for APIs to use.
*
* @generated from field: repeated google.protobuf.Any details = 3;
*/
details: Any[];
Expand Down
76 changes: 71 additions & 5 deletions ts/private/ts_proto_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,43 @@ load("@rules_proto//proto:proto_common.bzl", proto_toolchains = "toolchains")

_PROTO_TOOLCHAIN_TYPE = "@rules_proto//proto:toolchain_type"

# These 3 helpers are from "@protobuf//bazel/common:proto_common.bzl"
# After migrating, from @rules_proto to @protobuf, they can be replaced by a single load statement.
# See https://github.com/protocolbuffers/protobuf/blob/main/bazel/common/proto_common.bzl .

def _import_virtual_proto_path(path):
"""Imports all paths for virtual imports.
They're of the form:
'bazel-out/k8-fastbuild/bin/external/foo/e/_virtual_imports/e' or
'bazel-out/foo/k8-fastbuild/bin/e/_virtual_imports/e'"""
if path.count("/") > 4:
return "-I%s" % path
return None

def _import_repo_proto_path(path):
"""Imports all paths for generated files in external repositories.
They are of the form:
'bazel-out/k8-fastbuild/bin/external/foo' or
'bazel-out/foo/k8-fastbuild/bin'"""
path_count = path.count("/")
if path_count > 2 and path_count <= 4:
return "-I%s" % path
return None

def _import_main_output_proto_path(path):
"""Imports all paths for generated files or source files in external repositories.
They're of the form:
'bazel-out/k8-fastbuild/bin'
'external/foo'
'../foo'
"""
if path.count("/") <= 2 and path != ".":
return "-I%s" % path
return None

# buildifier: disable=function-docstring-header
def _protoc_action(ctx, proto_info, outputs):
"""Create an action like
Expand All @@ -18,6 +55,13 @@ def _protoc_action(ctx, proto_info, outputs):
"""
inputs = depset(proto_info.direct_sources, transitive = [proto_info.transitive_descriptor_sets])

# ensure that bin_dir doesn't get duplicated in the path
# e.g. by proto_library(strip_import_prefix=...)
proto_root = proto_info.proto_source_root
if proto_root.startswith(ctx.bin_dir.path):
proto_root = proto_root[len(ctx.bin_dir.path) + 1:]
plugin_output = ctx.bin_dir.path + "/" + proto_root

options = dict({
"keep_empty_files": True,
"target": "js+dts",
Expand All @@ -32,23 +76,38 @@ def _protoc_action(ctx, proto_info, outputs):
args.add_joined(["--plugin", "protoc-gen-es", ctx.executable.protoc_gen_es.path], join_with = "=")
for (key, value) in options.items():
args.add_joined(["--es_opt", key, value], join_with = "=")
args.add_joined(["--es_out", ctx.bin_dir.path], join_with = "=")
args.add_joined(["--es_out", plugin_output], join_with = "=")

if ctx.attr.gen_connect_es:
args.add_joined(["--plugin", "protoc-gen-connect-es", ctx.executable.protoc_gen_connect_es.path], join_with = "=")
for (key, value) in options.items():
args.add_joined(["--connect-es_opt", key, value], join_with = "=")
args.add_joined(["--connect-es_out", ctx.bin_dir.path], join_with = "=")
args.add_joined(["--connect-es_out", plugin_output], join_with = "=")

if ctx.attr.gen_connect_query:
args.add_joined(["--plugin", "protoc-gen-connect-query", ctx.executable.protoc_gen_connect_query.path], join_with = "=")
for (key, value) in options.items():
args.add_joined(["--connect-query_opt", key, value], join_with = "=")
args.add_joined(["--connect-query_out", ctx.bin_dir.path], join_with = "=")
args.add_joined(["--connect-query_out", plugin_output], join_with = "=")

args.add("--descriptor_set_in")
args.add_joined(proto_info.transitive_descriptor_sets, join_with = ctx.configuration.host_path_separator)

# Also from "@protobuf//bazel/common:proto_common.bzl":
#
# Protoc searches for .protos -I paths in order they are given and then
# uses the path within the directory as the package.
# This requires ordering the paths from most specific (longest) to least
# specific ones, so that no path in the list is a prefix of any of the
# following paths in the list.
# For example: 'bazel-out/k8-fastbuild/bin/external/foo' needs to be listed
# before 'bazel-out/k8-fastbuild/bin'. If not, protoc will discover file under
# the shorter path and use 'external/foo/...' as its package path.
args.add_all(proto_info.transitive_proto_path, map_each = _import_virtual_proto_path)
args.add_all(proto_info.transitive_proto_path, map_each = _import_repo_proto_path)
args.add_all(proto_info.transitive_proto_path, map_each = _import_main_output_proto_path)
args.add("-I.")

args.add_all(proto_info.direct_sources)

proto_toolchain_enabled = len(proto_toolchains.use_toolchain(_PROTO_TOOLCHAIN_TYPE)) > 0
Expand All @@ -72,10 +131,17 @@ def _declare_outs(ctx, info, ext):
if ctx.attr.gen_connect_es:
outs.extend(proto_common.declare_generated_files(ctx.actions, info, "_connect" + ext))
if ctx.attr.gen_connect_query:
proto_sources = info.direct_sources
proto_source_map = {src.basename: src for src in proto_sources}

# FIXME: we should refer to source files via labels instead of filenames
for proto, services in ctx.attr.gen_connect_query_service_mapping.items():
if not proto in proto_source_map:
fail("{} is not provided by proto_srcs".format(proto))
src = proto_source_map.get(proto)
prefix = proto.replace(".proto", "")
for service in services:
prefix = proto.replace(".proto", "")
outs.append(ctx.actions.declare_file("{}-{}_connectquery{}".format(prefix, service, ext)))
outs.append(ctx.actions.declare_file("{}-{}_connectquery{}".format(prefix, service, ext), sibling = src))

return outs

Expand Down

0 comments on commit ce58380

Please sign in to comment.