Skip to content

Commit ce7dd99

Browse files
authored
refactor: change from class methods to arrow functions (#92)
Big thanks to @koblas Now we support `--ts_opt=unary_rpc_promise` and `--ts_opt=grpc_package=xxx`
1 parent 0fbff05 commit ce7dd99

File tree

5 files changed

+1227
-1011
lines changed

5 files changed

+1227
-1011
lines changed

.prettierrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
proseWrap: always
2+
singleQuote: false
3+
trailingComma: all

README.md

+14-17
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
![npm](https://img.shields.io/npm/v/protoc-gen-ts)
55
![npm](https://img.shields.io/npm/dm/protoc-gen-ts)
66

7-
Generates appropriate Protocol Buffer sources from Proto files directly through _TypeScript Compiler API_.
8-
9-
This plugin generates plain **Typescript** files that can be used AMD, UMD, CommonJS module systems.
7+
Aim of this protoc plugin is to make usage of protocol buffers easy in Javascript/Typescript by taking modern approaches. This plugin generates plain **Typescript** files that can be used AMD, UMD, CommonJS module systems.
108

11-
Aim of this protoc plugin is to make usage of protocol buffers easy in Javascript/Typescript by taking modern approaches.
129

1310
## Example
1411

@@ -72,7 +69,7 @@ To overcome this problem, every generated message class has a static method call
7269
which can handle the mapping bidirectionally for you, even with the deeply structured messages. since it is
7370
aware of the field graph, it does not rely on any runtime type information thus we get the chance to keep it fast.
7471

75-
given the change example above, one can write code as;
72+
One can write code as;
7673

7774
```typescript
7875
const change = Change.fromObject({
@@ -85,13 +82,15 @@ const change = Change.fromObject({
8582
role: "maintainer"
8683
}
8784
});
85+
8886
console.log(change.author instanceof Author) // true
8987
```
9088

9189

9290
## Usage with `@grpc/grpc-js` or `grpc`
9391

94-
There is a seperate documentation for the usage of protoc-gen-ts along with either `@grpc/grpc-js` or `grpc`.
92+
There is a seperate documentation for the usage of protoc-gen-ts along with either `@grpc/grpc-js` or `grpc`. By default
93+
this generated gRPC interfaces will use `@grpc/grpc-js`.
9594

9695
Checkout [rpcs](docs/rpc.md).
9796

@@ -140,20 +139,12 @@ ts_proto_library(
140139
# Checkout the examples/bazel directory for an example.
141140
```
142141

143-
## Environment variables
144-
145-
```sh
146-
# This controls experimental features such as 'Promise' based rpcs.
147-
export EXPERIMENTAL_FEATURES=true;
142+
## Supported Options
148143

144+
* With `--ts_opt=unary_rpc_promise=true`, the service definition will contain a promise based rpc with a calling pattern of `const result = await client.METHOD(message)`. Note: all othe `metadata` and `options` parameters are still available to you.
149145

150-
# This controls the "import statement" for the outputs.
151-
# this is here for legacy purposes.
152-
export GRPC_PACKAGE_NAME="@grpc/grpc-js";
153-
# or
154-
export GRPC_PACKAGE_NAME="@grpc/grpc";
146+
* With `--ts_opt=grpc_package=xxxx`, you can specify a different package to import rather than `@grpc/grpc-js`.
155147

156-
```
157148
## Roadmap
158149

159150
- <s>Support for repeated non-integer fields</s>
@@ -178,10 +169,16 @@ export GRPC_PACKAGE_NAME="@grpc/grpc";
178169

179170
## Development
180171

172+
Generates appropriate Protocol Buffer sources from Proto files directly through _TypeScript Compiler API_.
173+
181174
```sh
182175
# to run test invoke
183176
yarn test
184177
# additionally if you want to see error details
185178
yarn test --test_output=errors
186179

187180
```
181+
182+
## Contributors
183+
184+
![GitHub Contributors Image](https://contrib.rocks/image?repo=thesayyn/protoc-gen-ts)

index.bzl

+5-5
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ def _ts_proto_library(ctx):
5252

5353
protoc_args.add("--descriptor_set_in=%s" % (":".join([desc.path for desc in transitive_descriptors])))
5454

55-
protoc_args.add_all(direct_sources)
56-
5755
env = dict()
5856

59-
env["GRPC_PACKAGE_NAME"] = ctx.attr.grpc_package_name
57+
protoc_args.add("--ts_opt=grpc_package=%s" % ctx.attr.grpc_package_name)
6058

6159
if ctx.attr.experimental_features:
62-
env['EXPERIMENTAL_FEATURES'] = "true"
60+
protoc_args.add("--ts_opt=unary_rpc_promise")
61+
62+
protoc_args.add_all(direct_sources)
6363

6464
ctx.actions.run(
6565
inputs = direct_sources + transitive_descriptors,
@@ -109,4 +109,4 @@ ts_proto_library = rule(
109109
),
110110

111111
}
112-
)
112+
)

src/index.js

+73-12
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,55 @@ function replaceExtension(filename, extension = ".ts") {
1919
return filename.replace(/\.[^/.]+$/, extension)
2020
}
2121

22+
/**
23+
* @typedef {{ unary_rpc_promise: boolean, grpc_package: string }} ConfigParameters
24+
*/
25+
26+
/**
27+
* @param {string | undefined | null} parameters
28+
* @return{ConfigParameters}
29+
*/
30+
function parseParameters(parameters) {
31+
/** @type{ConfigParameters} */
32+
const defaultValues = {
33+
unary_rpc_promise: false,
34+
grpc_package: "@grpc/grpc-js",
35+
};
36+
37+
/** @type{{ [K keyof ConfigParameters]: (value: string) => ConfigParameters[K] }} */
38+
const parsers = {
39+
unary_rpc_promise: (value) => value === "true",
40+
grpc_package: (value) => value,
41+
};
42+
43+
/** @type{Partial<ConfigParameters>} */
44+
const inputParams = {};
45+
46+
// comma separated
47+
(parameters || "").split(',').forEach(param => {
48+
const [key, value = "true"] = param.split('=', 2)
49+
50+
if (key in parsers) {
51+
inputParams[key] = parsers[key](value);
52+
}
53+
})
54+
55+
// Legacy Environment variables
56+
const legacy = {
57+
...(process.env.EXPERIMENTAL_FEATURES ? { unary_rpc_promise: true } : {}),
58+
...(process.env.GRPC_PACKAGE_NAME ? { grpc_package: process.env.GRPC_PACKAGE_NAME } : {}),
59+
}
60+
61+
return { ...defaultValues, ...legacy, ...inputParams }
62+
}
63+
2264
const request = plugin.CodeGeneratorRequest.deserialize(new Uint8Array(fs.readFileSync(0)));
2365
const response = new plugin.CodeGeneratorResponse({
2466
supported_features: plugin.CodeGeneratorResponse.Feature.FEATURE_PROTO3_OPTIONAL
2567
});
2668

69+
const configParams = parseParameters(request.parameter)
70+
2771
for (const descriptor of request.proto_file) {
2872
type.preprocess(descriptor, descriptor.name, `.${descriptor.package || ""}`);
2973
}
@@ -36,7 +80,6 @@ for (const fileDescriptor of request.proto_file) {
3680
// Will keep track of import statements
3781
const importStatements = [];
3882

39-
4083
// Create all named imports from dependencies
4184
for (const dependency of fileDescriptor.dependency) {
4285
const identifier = ts.factory.createUniqueName("dependency");
@@ -65,18 +108,37 @@ for (const fileDescriptor of request.proto_file) {
65108
importStatements.push(createImport(pbIdentifier, "google-protobuf"));
66109
}
67110

68-
// Create all services and clients
69-
for (const serviceDescriptor of fileDescriptor.service) {
70-
statements.push(rpc.createUnimplementedServer(fileDescriptor, serviceDescriptor, grpcIdentifier));
71-
statements.push(rpc.createServiceClient(fileDescriptor, serviceDescriptor, grpcIdentifier));
72-
}
73-
74-
// Import grpc only if there is service statements
75111
if (fileDescriptor.service.length) {
76-
importStatements.push(createImport(grpcIdentifier, process.env.GRPC_PACKAGE_NAME || "@grpc/grpc-js"));
112+
// Import grpc only if there is service statements
113+
importStatements.push(
114+
createImport(
115+
grpcIdentifier,
116+
configParams.grpc_package,
117+
)
118+
);
119+
statements.push(
120+
...rpc.createGrpcInterfaceType(fileDescriptor, grpcIdentifier, configParams)
121+
);
122+
// Create all services and clients
123+
for (const serviceDescriptor of fileDescriptor.service) {
124+
statements.push(
125+
rpc.createUnimplementedServer(
126+
fileDescriptor,
127+
serviceDescriptor,
128+
grpcIdentifier
129+
)
130+
);
131+
statements.push(
132+
rpc.createServiceClient(
133+
fileDescriptor,
134+
serviceDescriptor,
135+
grpcIdentifier,
136+
configParams,
137+
)
138+
);
139+
}
77140
}
78141

79-
80142
const {major, minor, patch} = request.compiler_version || {major: 0, minor: 0, patch: 0};
81143

82144
const doNotEditComment = ts.factory.createJSDocComment(
@@ -89,7 +151,6 @@ for (const fileDescriptor of request.proto_file) {
89151

90152
// Wrap statements within the namespace
91153
if (fileDescriptor.package) {
92-
93154
statements = [
94155
doNotEditComment,
95156
...importStatements,
@@ -127,4 +188,4 @@ for (const fileDescriptor of request.proto_file) {
127188
type.resetDependencyMap();
128189
}
129190

130-
process.stdout.write(response.serialize());
191+
process.stdout.write(response.serialize());

0 commit comments

Comments
 (0)