Skip to content

Commit b37b296

Browse files
mdouglassalexander-fenster
andcommittedApr 29, 2021
feat: add --no-service option for pbjs static target (#1577)
This option skips generation of service clients. Co-authored-by: Alexander Fenster <fenster@google.com>
1 parent 9201173 commit b37b296

File tree

3 files changed

+170
-1
lines changed

3 files changed

+170
-1
lines changed
 

‎cli/README.md

+163
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,168 @@ Command line interface (CLI) for [protobuf.js](https://github.com/dcodeIO/protob
77
* [CLI Documentation](https://github.com/dcodeIO/protobuf.js#command-line)
88

99
**Note** that moving the CLI to its own package is a work in progress. At the moment, it's still part of the main package.
10+
* [pbjs for JavaScript](#pbjs-for-javascript)
11+
* [pbts for TypeScript](#pbts-for-typescript)
12+
* [Reflection vs. static code](#reflection-vs-static-code)
13+
* [Command line API](#command-line-api)<br />
14+
15+
### pbjs for JavaScript
16+
17+
```
18+
Translates between file formats and generates static code.
19+
20+
-t, --target Specifies the target format. Also accepts a path to require a custom target.
21+
22+
json JSON representation
23+
json-module JSON representation as a module
24+
proto2 Protocol Buffers, Version 2
25+
proto3 Protocol Buffers, Version 3
26+
static Static code without reflection (non-functional on its own)
27+
static-module Static code without reflection as a module
28+
29+
-p, --path Adds a directory to the include path.
30+
31+
-o, --out Saves to a file instead of writing to stdout.
32+
33+
--sparse Exports only those types referenced from a main file (experimental).
34+
35+
Module targets only:
36+
37+
-w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
38+
39+
default Default wrapper supporting both CommonJS and AMD
40+
commonjs CommonJS wrapper
41+
amd AMD wrapper
42+
es6 ES6 wrapper (implies --es6)
43+
closure A closure adding to protobuf.roots where protobuf is a global
44+
45+
-r, --root Specifies an alternative protobuf.roots name.
46+
47+
-l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
48+
49+
eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
50+
51+
--es6 Enables ES6 syntax (const/let instead of var)
52+
53+
Proto sources only:
54+
55+
--keep-case Keeps field casing instead of converting to camel case.
56+
57+
Static targets only:
58+
59+
--no-create Does not generate create functions used for reflection compatibility.
60+
--no-encode Does not generate encode functions.
61+
--no-decode Does not generate decode functions.
62+
--no-verify Does not generate verify functions.
63+
--no-convert Does not generate convert functions like from/toObject
64+
--no-delimited Does not generate delimited encode/decode functions.
65+
--no-beautify Does not beautify generated code.
66+
--no-comments Does not output any JSDoc comments.
67+
--no-service Does not output service classes.
68+
69+
--force-long Enforces the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
70+
--force-number Enforces the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
71+
--force-message Enforces the use of message instances instead of plain objects.
72+
73+
usage: pbjs [options] file1.proto file2.json ... (or pipe) other | pbjs [options] -
74+
```
75+
76+
For production environments it is recommended to bundle all your .proto files to a single .json file, which minimizes the number of network requests and avoids any parser overhead (hint: works with just the **light** library):
77+
78+
```
79+
$> pbjs -t json file1.proto file2.proto > bundle.json
80+
```
81+
82+
Now, either include this file in your final bundle:
83+
84+
```js
85+
var root = protobuf.Root.fromJSON(require("./bundle.json"));
86+
```
87+
88+
or load it the usual way:
89+
90+
```js
91+
protobuf.load("bundle.json", function(err, root) {
92+
...
93+
});
94+
```
95+
96+
Generated static code, on the other hand, works with just the **minimal** library. For example
97+
98+
```
99+
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
100+
```
101+
102+
will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
103+
104+
**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
105+
106+
107+
### pbts for TypeScript
108+
109+
```
110+
Generates TypeScript definitions from annotated JavaScript files.
111+
112+
-o, --out Saves to a file instead of writing to stdout.
113+
114+
-g, --global Name of the global object in browser environments, if any.
115+
116+
--no-comments Does not output any JSDoc comments.
117+
118+
Internal flags:
119+
120+
-n, --name Wraps everything in a module of the specified name.
121+
122+
-m, --main Whether building the main library without any imports.
123+
124+
usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
125+
```
126+
127+
Picking up on the example above, the following not only generates static code to a CommonJS module `compiled.js` but also its respective TypeScript definitions to `compiled.d.ts`:
128+
129+
```
130+
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
131+
$> pbts -o compiled.d.ts compiled.js
132+
```
133+
134+
Additionally, TypeScript definitions of static modules are compatible with their reflection-based counterparts (i.e. as exported by JSON modules), as long as the following conditions are met:
135+
136+
1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
137+
2. Types, services and enums must start with an uppercase letter to become available as properties of the reflected types as well (i.e. to be able to use `MyMessage.MyEnum` instead of `root.lookup("MyMessage.MyEnum")`).
138+
139+
For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
140+
141+
```
142+
$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
143+
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
144+
```
145+
146+
### Reflection vs. static code
147+
148+
While using .proto files directly requires the full library respectively pure reflection/JSON the light library, pretty much all code but the relatively short descriptors is shared.
149+
150+
Static code, on the other hand, requires just the minimal library, but generates additional source code without any reflection features. This also implies that there is a break-even point where statically generated code becomes larger than descriptor-based code once the amount of code generated exceeds the size of the full respectively light library.
151+
152+
There is no significant difference performance-wise as the code generated statically is pretty much the same as generated at runtime and both are largely interchangeable as seen in the previous section.
153+
154+
| Source | Library | Advantages | Tradeoffs
155+
|--------|---------|------------|-----------
156+
| .proto | full | Easily editable<br />Interoperability with other libraries<br />No compile step | Some parsing and possibly network overhead
157+
| JSON | light | Easily editable<br />No parsing overhead<br />Single bundle (no network overhead) | protobuf.js specific<br />Has a compile step
158+
| static | minimal | Works where `eval` access is restricted<br />Fully documented<br />Small footprint for small protos | Can be hard to edit<br />No reflection<br />Has a compile step
159+
160+
### Command line API
161+
162+
Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
163+
164+
```js
165+
var pbjs = require("protobufjs-cli/pbjs"); // or require("protobufjs-cli").pbjs / .pbts
166+
167+
pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
168+
if (err)
169+
throw err;
170+
// do something with output
171+
});
172+
```
10173

11174
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)

‎cli/pbjs.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ exports.main = function main(args, callback) {
4444
"force-message": "strict-message"
4545
},
4646
string: [ "target", "out", "path", "wrap", "dependency", "root", "lint" ],
47-
boolean: [ "create", "encode", "decode", "verify", "convert", "delimited", "beautify", "comments", "es6", "sparse", "keep-case", "force-long", "force-number", "force-enum-string", "force-message" ],
47+
boolean: [ "create", "encode", "decode", "verify", "convert", "delimited", "beautify", "comments", "service", "es6", "sparse", "keep-case", "force-long", "force-number", "force-enum-string", "force-message" ],
4848
default: {
4949
target: "json",
5050
create: true,
@@ -55,6 +55,7 @@ exports.main = function main(args, callback) {
5555
delimited: true,
5656
beautify: true,
5757
comments: true,
58+
service: true,
5859
es6: null,
5960
lint: lintDefault,
6061
"keep-case": false,
@@ -135,6 +136,7 @@ exports.main = function main(args, callback) {
135136
" --no-delimited Does not generate delimited encode/decode functions.",
136137
" --no-beautify Does not beautify generated code.",
137138
" --no-comments Does not output any JSDoc comments.",
139+
" --no-service Does not output service classes.",
138140
"",
139141
" --force-long Enfores the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.",
140142
" --force-number Enfores the use of 'number' for s-/u-/int64 and s-/fixed64 fields.",

‎cli/targets/static.js

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ function aOrAn(name) {
109109
function buildNamespace(ref, ns) {
110110
if (!ns)
111111
return;
112+
113+
if (ns instanceof Service && !config.service)
114+
return;
115+
112116
if (ns.name !== "") {
113117
push("");
114118
if (!ref && config.es6)

0 commit comments

Comments
 (0)
Please sign in to comment.