Skip to content

Commit 4bfe0c2

Browse files
committed
CLI: More progress on decoupling the CLI; Docs: Explained the JSON structure in README and moved CLI specific information to the CLI package
1 parent 8a60174 commit 4bfe0c2

File tree

7 files changed

+255
-189
lines changed

7 files changed

+255
-189
lines changed

README.md

Lines changed: 23 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,7 @@ protobuf.load("awesome.proto")
252252

253253
### Using JSON descriptors
254254

255-
The library utilizes a JSON format that is equivalent to a .proto definition (see also: [Command line usage](#command-line)).
256-
257-
The following is identical to the .proto definition seen above, but it can also be used with just the light library because it doesn't require the parser:
255+
The library utilizes a JSON format that is equivalent to a .proto definition. For example, the following is identical to the .proto definition seen above:
258256

259257
```json
260258
// awesome.json
@@ -272,6 +270,25 @@ The following is identical to the .proto definition seen above, but it can also
272270
}
273271
```
274272

273+
The JSON format closely resembles the internal reflection structure:
274+
275+
| Type (T) | Extends | Type-specific properties
276+
|--------------------|--------------------|-------------------------
277+
| *ReflectionObject* | | options
278+
| *Namespace* | *ReflectionObject* | nested
279+
| Type | *Namespace* | **fields**
280+
| Enum | *ReflectionObject* | **values**
281+
| Field | *ReflectionObject* | rule, **type**, **id**
282+
| MapField | Field | **keyType**
283+
| Service | *Namespace* | **methods**
284+
| Method | *ReflectionObject* | *type*, **requestType**, **responseType**, requestStream, responseStream
285+
286+
* **Bold** properties are required. *Italic* types are abstract.
287+
* `T.fromJSON(name, json)` creates the respective reflection object from a JSON descriptor
288+
* `T#toJSON()` creates a JSON descriptor from the respective reflection object (`name` is used as the key within the parent)
289+
290+
Exclusively using JSON instead of .proto files enables the use of just the light library (the parser isn't required in this case).
291+
275292
A JSON descriptor can either be loaded the usual way:
276293

277294
```js
@@ -438,9 +455,7 @@ protobuf.load("awesome.proto", function(err, root) {
438455
});
439456
```
440457

441-
To achieve the same with static code generated by [pbjs](#command-line), there is the [pbts](#generating-typescript-definitions-from-static-modules) command line utility to generate type definitions from static code as well.
442-
443-
Let's say you generated your static code to `bundle.js` and its type definitions to `bundle.d.ts`, then you can do:
458+
If you generated static code using the CLI to `bundle.js` and its type definitions to `bundle.d.ts`, then you can do:
444459

445460
```ts
446461
import * as root from "./bundle.js";
@@ -470,6 +485,7 @@ Documentation
470485

471486
#### protobuf.js
472487
* [API Documentation](http://dcode.io/protobuf.js)
488+
* [CLI Documentation](./cli/README.md)
473489
* [CHANGELOG](https://github.com/dcodeIO/protobuf.js/blob/master/CHANGELOG.md)
474490
* [Frequently asked questions](https://github.com/dcodeIO/protobuf.js/wiki) on our wiki
475491

@@ -478,152 +494,7 @@ Documentation
478494

479495
Command line
480496
------------
481-
482-
The `pbjs` command line utility can be used to bundle and translate between .proto and .json files. It also generates static code.
483-
484-
```
485-
Consolidates imports and converts between file formats.
486-
487-
-t, --target Specifies the target format. Also accepts a path to require a custom target.
488-
489-
json JSON representation
490-
json-module JSON representation as a module
491-
proto2 Protocol Buffers, Version 2
492-
proto3 Protocol Buffers, Version 3
493-
static Static code without reflection
494-
static-module Static code without reflection as a module
495-
496-
-p, --path Adds a directory to the include path.
497-
498-
-o, --out Saves to a file instead of writing to stdout.
499-
500-
Module targets only:
501-
502-
-w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
503-
504-
default Default wrapper supporting both CommonJS and AMD
505-
commonjs CommonJS wrapper
506-
amd AMD wrapper
507-
es6 ES6 wrapper (implies --es6)
508-
509-
-r, --root Specifies an alternative protobuf.roots name.
510-
511-
-l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
512-
513-
eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
514-
515-
--es6 Enables ES6 syntax (const/let instead of var)
516-
517-
Proto sources only:
518-
519-
--keep-case Keeps field casing instead of converting to camel case.
520-
521-
Static targets only:
522-
523-
--no-create Does not generate create functions used for reflection compatibility.
524-
--no-encode Does not generate encode functions.
525-
--no-decode Does not generate decode functions.
526-
--no-verify Does not generate verify functions.
527-
--no-convert Does not generate convert functions like from/toObject
528-
--no-delimited Does not generate delimited encode/decode functions.
529-
--no-beautify Does not beautify generated code.
530-
--no-comments Does not output any JSDoc comments.
531-
532-
usage: pbjs [options] file1.proto file2.json ... (or) other | pbjs [options] -
533-
```
534-
535-
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](#distributions)):
536-
537-
```
538-
$> pbjs -t json file1.proto file2.proto > bundle.json
539-
```
540-
541-
Now, either include this file in your final bundle:
542-
543-
```js
544-
var root = protobuf.Root.fromJSON(require("./bundle.json"));
545-
```
546-
547-
or load it the usual way:
548-
549-
```js
550-
protobuf.load("bundle.json", function(err, root) {
551-
...
552-
});
553-
```
554-
555-
The `pbjs` utility is also capable of generating static code (hint: works with just the [minimal library](#distributions)). For example
556-
557-
```
558-
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
559-
```
560-
561-
will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
562-
563-
**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
564-
565-
### Generating TypeScript definitions from static modules
566-
567-
Likewise, the `pbts` command line utility can be used to generate TypeScript definitions from `pbjs`-generated static modules.
568-
569-
```
570-
Generates TypeScript definitions from annotated JavaScript files.
571-
572-
-o, --out Saves to a file instead of writing to stdout.
573-
574-
-g, --global Name of the global object in browser environments, if any.
575-
576-
--no-comments Does not output any JSDoc comments.
577-
578-
Internal flags:
579-
580-
-n, --name Wraps everything in a module of the specified name.
581-
582-
-m, --main Whether building the main library without any imports.
583-
584-
usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
585-
```
586-
587-
Picking up on the example above, the following not just generates static code to a CommonJS module `compiled.js` but also its respective TypeScript definitions to `compiled.d.ts`:
588-
589-
```
590-
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
591-
$> pbts -o compiled.d.ts compiled.js
592-
```
593-
594-
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:
595-
596-
1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
597-
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")`).
598-
599-
For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
600-
601-
```
602-
$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
603-
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
604-
```
605-
606-
### On reflection vs. static code
607-
608-
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.
609-
610-
Static code, on the other hand, requires just the minimal library, but generates additional, albeit editable, source code without any reflection features.
611-
612-
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.
613-
614-
### Using pbjs and pbts programmatically
615-
616-
Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
617-
618-
```js
619-
var pbjs = require("protobufjs/cli/pbjs");
620-
621-
pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
622-
if (err)
623-
throw err;
624-
// do something with output
625-
});
626-
```
497+
Command line usage has moved to the (soon to be decoupled) [CLI package]((./cli/README.md))
627498

628499
Performance
629500
-----------

cli/README.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
protobufjs-cli
2+
==============
3+
[![npm](https://img.shields.io/npm/v/protobufjscli.svg)](https://www.npmjs.com/package/protobufjs-cli)
4+
5+
Command line interface (CLI) for [protobuf.js](https://github.com/dcodeIO/protobuf.js). Translates between file formats and generates static code as well as TypeScript definitions.
6+
7+
Contents
8+
--------
9+
10+
<!--
11+
12+
* [Installation](#installation)<br />
13+
How to get started using the CLI.
14+
15+
-->
16+
17+
* [Usage](#usage)<br />
18+
An introduction to the toolset.
19+
20+
* [API](#api)<br />
21+
Details on using pbjs and pbts programmatically.
22+
23+
<!--
24+
25+
Installation
26+
------------
27+
28+
```
29+
$> npm install protobufjs protobufjs-cli [--save --save-prefix=~]
30+
```
31+
32+
Note that the CLI package is tightly coupled to the main package, so don't forget to update it as well.
33+
34+
-->
35+
36+
Usage
37+
-----
38+
39+
### pbjs
40+
41+
```
42+
Translates between file formats and generates static code.
43+
44+
-t, --target Specifies the target format. Also accepts a path to require a custom target.
45+
46+
json JSON representation
47+
json-module JSON representation as a module
48+
proto2 Protocol Buffers, Version 2
49+
proto3 Protocol Buffers, Version 3
50+
static Static code without reflection
51+
static-module Static code without reflection as a module
52+
53+
-p, --path Adds a directory to the include path.
54+
55+
-o, --out Saves to a file instead of writing to stdout.
56+
57+
Module targets only:
58+
59+
-w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
60+
61+
default Default wrapper supporting both CommonJS and AMD
62+
commonjs CommonJS wrapper
63+
amd AMD wrapper
64+
es6 ES6 wrapper (implies --es6)
65+
66+
-r, --root Specifies an alternative protobuf.roots name.
67+
68+
-l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
69+
70+
eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
71+
72+
--es6 Enables ES6 syntax (const/let instead of var)
73+
74+
Proto sources only:
75+
76+
--keep-case Keeps field casing instead of converting to camel case.
77+
78+
Static targets only:
79+
80+
--no-create Does not generate create functions used for reflection compatibility.
81+
--no-encode Does not generate encode functions.
82+
--no-decode Does not generate decode functions.
83+
--no-verify Does not generate verify functions.
84+
--no-convert Does not generate convert functions like from/toObject
85+
--no-delimited Does not generate delimited encode/decode functions.
86+
--no-beautify Does not beautify generated code.
87+
--no-comments Does not output any JSDoc comments.
88+
89+
usage: pbjs [options] file1.proto file2.json ... (or) other | pbjs [options] -
90+
```
91+
92+
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):
93+
94+
```
95+
$> pbjs -t json file1.proto file2.proto > bundle.json
96+
```
97+
98+
Now, either include this file in your final bundle:
99+
100+
```js
101+
var root = protobuf.Root.fromJSON(require("./bundle.json"));
102+
```
103+
104+
or load it the usual way:
105+
106+
```js
107+
protobuf.load("bundle.json", function(err, root) {
108+
...
109+
});
110+
```
111+
112+
Generated static code, on the other hand, works with just the **minimal** library. For example
113+
114+
```
115+
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
116+
```
117+
118+
will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
119+
120+
**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
121+
122+
123+
### pbts
124+
125+
```
126+
Generates TypeScript definitions from annotated JavaScript files.
127+
128+
-o, --out Saves to a file instead of writing to stdout.
129+
130+
-g, --global Name of the global object in browser environments, if any.
131+
132+
--no-comments Does not output any JSDoc comments.
133+
134+
Internal flags:
135+
136+
-n, --name Wraps everything in a module of the specified name.
137+
138+
-m, --main Whether building the main library without any imports.
139+
140+
usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
141+
```
142+
143+
Picking up on the example above, the following not just generates static code to a CommonJS module `compiled.js` but also its respective TypeScript definitions to `compiled.d.ts`:
144+
145+
```
146+
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
147+
$> pbts -o compiled.d.ts compiled.js
148+
```
149+
150+
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:
151+
152+
1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
153+
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")`).
154+
155+
For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
156+
157+
```
158+
$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
159+
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
160+
```
161+
162+
### Reflection vs. static code
163+
164+
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.
165+
166+
Static code, on the other hand, requires just the minimal library, but generates additional, albeit editable, source code without any reflection features.
167+
168+
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.
169+
170+
API
171+
---
172+
173+
Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
174+
175+
```js
176+
var pbjs = require("protobufjs-cli/pbjs"); // or require("protobufjs-cli").pbjs / .pbts
177+
178+
pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
179+
if (err)
180+
throw err;
181+
// do something with output
182+
});
183+
```
184+
185+
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)

0 commit comments

Comments
 (0)