Skip to content

Commit 40ad11c

Browse files
acozzetteclaude
andauthored
feat: add js_rpc_library and js_rpc_toolchain for ConnectRPC support (#2797)
Adds a new `js_rpc_library` rule and `js_rpc_toolchain` macro to support protoc-based RPC code generators such as `protoc-gen-connect-query`. - `js_rpc_library`: a rule that runs a protoc plugin on its immediate proto_library deps and exposes the output as JsInfo. - `js_rpc_toolchain`: a macro wrapping `_js_proto_toolchain` but with a new `//js/toolchains:protoc_rpc_plugin` toolchain type. - Updates to `e2e/protobuf-es` showing how to use Connect and Connect-Query - Updates to `e2/protobuf-google` showing how to use grpc-js Support for Connect-Query seems to be the only thing in the deprecated `ts_proto_library` rule that was lacking in `rules_js`. Hopefully now that we have support for it, we can start recommending that everyone migrate away from `ts_proto_library`. --- ### Changes are visible to end-users: yes - Searched for relevant documentation and updated as needed: no - Breaking change (forces users to change their own code or config): no - Suggested release notes appear below: yes A `js_rpc_library` rule is now available and can generate RPC bindings for any RPC system that is built on a protoc plugin. The plugin just needs to be registered with the `js_rpc_toolchain` macro. ### Test plan - New test cases added --------- Co-authored-by: Claude Sonnet 4.6 <[email protected]>
1 parent 401406a commit 40ad11c

37 files changed

Lines changed: 1323 additions & 69 deletions

MODULE.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ use_repo(
8888

8989
####### Dev dependencies ########
9090

91+
register_toolchains(
92+
"//js/private/test/proto:proto_toolchain_for_tests_toolchain",
93+
"//js/private/test/proto:rpc_toolchain_for_tests_toolchain",
94+
dev_dependency = True,
95+
)
96+
9197
# Dev-only pnpm used for local testing
9298
pnpm10 = use_extension("@aspect_rules_js//npm:extensions.bzl", "pnpm", dev_dependency = True)
9399
pnpm10.pnpm(

e2e/protobuf-es/.bazelversion

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
../../../.bazelversion
1+
../../.bazelversion

e2e/protobuf-es/BUILD.bazel

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
load("@aspect_rules_js//js:defs.bzl", "js_library", "js_test")
2+
load("@aspect_rules_js//js:rpc.bzl", "js_rpc_library")
23
load("@npm//:defs.bzl", "npm_link_all_packages")
34
load("@protobuf//bazel:proto_library.bzl", "proto_library")
45

@@ -38,3 +39,50 @@ js_test(
3839
data = [":test_lib"],
3940
entry_point = "test_proto.js",
4041
)
42+
43+
js_library(
44+
name = "test_connect_lib",
45+
srcs = ["test_connect.js"],
46+
deps = [
47+
":node_modules/@connectrpc/connect",
48+
":user_proto",
49+
],
50+
)
51+
52+
js_test(
53+
name = "test_connect",
54+
data = [":test_connect_lib"],
55+
entry_point = "test_connect.js",
56+
)
57+
58+
proto_library(
59+
name = "eliza_proto",
60+
srcs = ["eliza.proto"],
61+
)
62+
63+
js_rpc_library(
64+
name = "eliza_rpc",
65+
outs = [
66+
"eliza-ElizaService_connectquery.d.ts",
67+
"eliza-ElizaService_connectquery.js",
68+
],
69+
deps = [":eliza_proto"],
70+
)
71+
72+
js_library(
73+
name = "test_connect_query_lib",
74+
srcs = ["test_connect_query.js"],
75+
deps = [
76+
":eliza_proto",
77+
":eliza_rpc",
78+
":node_modules/@bufbuild/protobuf",
79+
":node_modules/@connectrpc/connect",
80+
":node_modules/@connectrpc/connect-query-core",
81+
],
82+
)
83+
84+
js_test(
85+
name = "test_connect_query",
86+
data = [":test_connect_query_lib"],
87+
entry_point = "test_connect_query.js",
88+
)

e2e/protobuf-es/MODULE.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
bazel_dep(name = "aspect_rules_js")
22
bazel_dep(name = "bazel_skylib", version = "1.8.2")
3-
bazel_dep(name = "diff.bzl", version = "0.4.3")
43
bazel_dep(name = "protobuf", version = "33.4") # Works with Bazel 7-9
54
bazel_dep(name = "rules_nodejs", version = "6.7.3")
65

e2e/protobuf-es/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Buf.build protobuf-es example
22

33
This directory contains an example of how to set up and use the Buf.build
4-
protobuf-es implementation. See also e2e/protobuf-google/ for an example of how
5-
to use Google's protobuf implementation.
4+
protobuf-es implementation, along with Connect and Connect-Query. See also
5+
e2e/protobuf-google/ for an example of how to use Google's protobuf
6+
implementation.
67

78
Ideally we would like to support every JavaScript or TypeScript implementation
89
for which Buf [provides](https://buf.build/bazel/bazel/sdks/main:protobuf) an

e2e/protobuf-es/eliza.proto

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
syntax = "proto3";
2+
3+
package eliza.v1;
4+
5+
message SayRequest {
6+
string sentence = 1;
7+
}
8+
9+
message SayResponse {
10+
string sentence = 1;
11+
}
12+
13+
service ElizaService {
14+
// Say returns the input message back.
15+
rpc Say(SayRequest) returns (SayResponse) {}
16+
}

e2e/protobuf-es/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"private": true,
33
"packageManager": "[email protected]",
44
"dependencies": {
5-
"@bufbuild/protobuf": "catalog:"
5+
"@bufbuild/protobuf": "catalog:",
6+
"@connectrpc/connect": "catalog:",
7+
"@connectrpc/connect-query-core": "catalog:"
68
},
79
"type": "module"
810
}

e2e/protobuf-es/pnpm-lock.yaml

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/protobuf-es/pnpm-workspace.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ packages:
33

44
catalog:
55
'@bufbuild/protobuf': '2.7.0'
6+
'@connectrpc/connect': '2.1.1'
7+
'@connectrpc/connect-query-core': '2.2.0'
68

79
onlyBuiltDependencies: []

e2e/protobuf-es/test_connect.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { GetUserRequestSchema, UserSchema, UserService } from './user_pb.js'
2+
import { createClient, createRouterTransport } from '@connectrpc/connect'
3+
import { create } from '@bufbuild/protobuf'
4+
import assert from 'node:assert'
5+
6+
// In protobuf-es v2, service descriptors are embedded in the _pb.js file
7+
// alongside message schemas, so no separate codegen step is needed.
8+
assert.ok(UserService, 'UserService should be defined')
9+
assert.ok(UserService.method.getUser, 'getUser method should be defined')
10+
11+
const transport = createRouterTransport((router) => {
12+
router.service(UserService, {
13+
getUser(req) {
14+
return create(UserSchema, { name: req.name })
15+
},
16+
})
17+
})
18+
19+
const client = createClient(UserService, transport)
20+
const response = await client.getUser(
21+
create(GetUserRequestSchema, { name: 'alice' })
22+
)
23+
assert.equal(response.name, 'alice')

0 commit comments

Comments
 (0)