diff --git a/README.md b/README.md
index caa0ed7c8..68ce7a0f9 100644
--- a/README.md
+++ b/README.md
@@ -252,9 +252,7 @@ protobuf.load("awesome.proto")
### Using JSON descriptors
-The library utilizes a JSON format that is equivalent to a .proto definition (see also: [Command line usage](#command-line)).
-
-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:
+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:
```json
// awesome.json
@@ -272,6 +270,25 @@ The following is identical to the .proto definition seen above, but it can also
}
```
+The JSON format closely resembles the internal reflection structure:
+
+| Type (T) | Extends | Type-specific properties
+|--------------------|--------------------|-------------------------
+| *ReflectionObject* | | options
+| *Namespace* | *ReflectionObject* | nested
+| Type | *Namespace* | **fields**
+| Enum | *ReflectionObject* | **values**
+| Field | *ReflectionObject* | rule, **type**, **id**
+| MapField | Field | **keyType**
+| Service | *Namespace* | **methods**
+| Method | *ReflectionObject* | *type*, **requestType**, **responseType**, requestStream, responseStream
+
+* **Bold** properties are required. *Italic* types are abstract.
+* `T.fromJSON(name, json)` creates the respective reflection object from a JSON descriptor
+* `T#toJSON()` creates a JSON descriptor from the respective reflection object (`name` is used as the key within the parent)
+
+Exclusively using JSON instead of .proto files enables the use of just the light library (the parser isn't required in this case).
+
A JSON descriptor can either be loaded the usual way:
```js
@@ -438,9 +455,7 @@ protobuf.load("awesome.proto", function(err, root) {
});
```
-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.
-
-Let's say you generated your static code to `bundle.js` and its type definitions to `bundle.d.ts`, then you can do:
+If you generated static code using the CLI to `bundle.js` and its type definitions to `bundle.d.ts`, then you can do:
```ts
import * as root from "./bundle.js";
@@ -470,6 +485,7 @@ Documentation
#### protobuf.js
* [API Documentation](http://dcode.io/protobuf.js)
+* [CLI Documentation](./cli/README.md)
* [CHANGELOG](https://github.com/dcodeIO/protobuf.js/blob/master/CHANGELOG.md)
* [Frequently asked questions](https://github.com/dcodeIO/protobuf.js/wiki) on our wiki
@@ -478,152 +494,7 @@ Documentation
Command line
------------
-
-The `pbjs` command line utility can be used to bundle and translate between .proto and .json files. It also generates static code.
-
-```
-Consolidates imports and converts between file formats.
-
- -t, --target Specifies the target format. Also accepts a path to require a custom target.
-
- json JSON representation
- json-module JSON representation as a module
- proto2 Protocol Buffers, Version 2
- proto3 Protocol Buffers, Version 3
- static Static code without reflection
- static-module Static code without reflection as a module
-
- -p, --path Adds a directory to the include path.
-
- -o, --out Saves to a file instead of writing to stdout.
-
- Module targets only:
-
- -w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
-
- default Default wrapper supporting both CommonJS and AMD
- commonjs CommonJS wrapper
- amd AMD wrapper
- es6 ES6 wrapper (implies --es6)
-
- -r, --root Specifies an alternative protobuf.roots name.
-
- -l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
-
- eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
-
- --es6 Enables ES6 syntax (const/let instead of var)
-
- Proto sources only:
-
- --keep-case Keeps field casing instead of converting to camel case.
-
- Static targets only:
-
- --no-create Does not generate create functions used for reflection compatibility.
- --no-encode Does not generate encode functions.
- --no-decode Does not generate decode functions.
- --no-verify Does not generate verify functions.
- --no-convert Does not generate convert functions like from/toObject
- --no-delimited Does not generate delimited encode/decode functions.
- --no-beautify Does not beautify generated code.
- --no-comments Does not output any JSDoc comments.
-
-usage: pbjs [options] file1.proto file2.json ... (or) other | pbjs [options] -
-```
-
-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)):
-
-```
-$> pbjs -t json file1.proto file2.proto > bundle.json
-```
-
-Now, either include this file in your final bundle:
-
-```js
-var root = protobuf.Root.fromJSON(require("./bundle.json"));
-```
-
-or load it the usual way:
-
-```js
-protobuf.load("bundle.json", function(err, root) {
- ...
-});
-```
-
-The `pbjs` utility is also capable of generating static code (hint: works with just the [minimal library](#distributions)). For example
-
-```
-$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
-```
-
-will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
-
-**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
-
-### Generating TypeScript definitions from static modules
-
-Likewise, the `pbts` command line utility can be used to generate TypeScript definitions from `pbjs`-generated static modules.
-
-```
-Generates TypeScript definitions from annotated JavaScript files.
-
- -o, --out Saves to a file instead of writing to stdout.
-
- -g, --global Name of the global object in browser environments, if any.
-
- --no-comments Does not output any JSDoc comments.
-
- Internal flags:
-
- -n, --name Wraps everything in a module of the specified name.
-
- -m, --main Whether building the main library without any imports.
-
-usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
-```
-
-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`:
-
-```
-$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
-$> pbts -o compiled.d.ts compiled.js
-```
-
-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:
-
-1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
-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")`).
-
-For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
-
-```
-$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
-$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
-```
-
-### On reflection vs. static code
-
-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.
-
-Static code, on the other hand, requires just the minimal library, but generates additional, albeit editable, source code without any reflection features.
-
-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.
-
-### Using pbjs and pbts programmatically
-
-Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
-
-```js
-var pbjs = require("protobufjs/cli/pbjs");
-
-pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
- if (err)
- throw err;
- // do something with output
-});
-```
+Command line usage has moved to the (soon to be decoupled) [CLI package]((./cli/README.md))
Performance
-----------
diff --git a/cli/README.md b/cli/README.md
new file mode 100644
index 000000000..2bc3b589e
--- /dev/null
+++ b/cli/README.md
@@ -0,0 +1,185 @@
+protobufjs-cli
+==============
+[![npm](https://img.shields.io/npm/v/protobufjscli.svg)](https://www.npmjs.com/package/protobufjs-cli)
+
+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.
+
+Contents
+--------
+
+
+
+* [Usage](#usage)
+ An introduction to the toolset.
+
+* [API](#api)
+ Details on using pbjs and pbts programmatically.
+
+
+
+Usage
+-----
+
+### pbjs
+
+```
+Translates between file formats and generates static code.
+
+ -t, --target Specifies the target format. Also accepts a path to require a custom target.
+
+ json JSON representation
+ json-module JSON representation as a module
+ proto2 Protocol Buffers, Version 2
+ proto3 Protocol Buffers, Version 3
+ static Static code without reflection
+ static-module Static code without reflection as a module
+
+ -p, --path Adds a directory to the include path.
+
+ -o, --out Saves to a file instead of writing to stdout.
+
+ Module targets only:
+
+ -w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
+
+ default Default wrapper supporting both CommonJS and AMD
+ commonjs CommonJS wrapper
+ amd AMD wrapper
+ es6 ES6 wrapper (implies --es6)
+
+ -r, --root Specifies an alternative protobuf.roots name.
+
+ -l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
+
+ eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
+
+ --es6 Enables ES6 syntax (const/let instead of var)
+
+ Proto sources only:
+
+ --keep-case Keeps field casing instead of converting to camel case.
+
+ Static targets only:
+
+ --no-create Does not generate create functions used for reflection compatibility.
+ --no-encode Does not generate encode functions.
+ --no-decode Does not generate decode functions.
+ --no-verify Does not generate verify functions.
+ --no-convert Does not generate convert functions like from/toObject
+ --no-delimited Does not generate delimited encode/decode functions.
+ --no-beautify Does not beautify generated code.
+ --no-comments Does not output any JSDoc comments.
+
+usage: pbjs [options] file1.proto file2.json ... (or) other | pbjs [options] -
+```
+
+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):
+
+```
+$> pbjs -t json file1.proto file2.proto > bundle.json
+```
+
+Now, either include this file in your final bundle:
+
+```js
+var root = protobuf.Root.fromJSON(require("./bundle.json"));
+```
+
+or load it the usual way:
+
+```js
+protobuf.load("bundle.json", function(err, root) {
+ ...
+});
+```
+
+Generated static code, on the other hand, works with just the **minimal** library. For example
+
+```
+$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
+```
+
+will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
+
+**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
+
+
+### pbts
+
+```
+Generates TypeScript definitions from annotated JavaScript files.
+
+ -o, --out Saves to a file instead of writing to stdout.
+
+ -g, --global Name of the global object in browser environments, if any.
+
+ --no-comments Does not output any JSDoc comments.
+
+ Internal flags:
+
+ -n, --name Wraps everything in a module of the specified name.
+
+ -m, --main Whether building the main library without any imports.
+
+usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
+```
+
+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`:
+
+```
+$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
+$> pbts -o compiled.d.ts compiled.js
+```
+
+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:
+
+1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
+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")`).
+
+For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
+
+```
+$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
+$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
+```
+
+### Reflection vs. static code
+
+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.
+
+Static code, on the other hand, requires just the minimal library, but generates additional, albeit editable, source code without any reflection features.
+
+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.
+
+API
+---
+
+Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
+
+```js
+var pbjs = require("protobufjs-cli/pbjs"); // or require("protobufjs-cli").pbjs / .pbts
+
+pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
+ if (err)
+ throw err;
+ // do something with output
+});
+```
+
+**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
diff --git a/cli/package.json b/cli/package.json
index a21f4f2c8..9e26dfeeb 100644
--- a/cli/package.json
+++ b/cli/package.json
@@ -1,32 +1 @@
-{
- "name": "protobufjs-cli",
- "description": "protobuf.js command line interface (CLI).",
- "version": "6.7.0",
- "author": "Daniel Wirtz ",
- "repository": {
- "type": "git",
- "url": "https://github.com/dcodeIO/protobuf.js.git"
- },
- "license": "BSD-3-Clause",
- "main": "index.js",
- "types": "index.d.ts",
- "bin": {
- "pbjs": "bin/pbjs",
- "pbts": "bin/pbts"
- },
- "peerDependencies": {
- "protobufjs": "6.7.0"
- },
- "dependencies": {
- "chalk": "^1.1.3",
- "escodegen": "^1.8.1",
- "espree": "^3.1.3",
- "estraverse": "^4.2.0",
- "glob": "^7.1.1",
- "jsdoc": "^3.4.2",
- "minimist": "^1.2.0",
- "semver": "^5.3.0",
- "tmp": "0.0.31",
- "uglify-js": "^2.8.15"
- }
-}
\ No newline at end of file
+{}
\ No newline at end of file
diff --git a/cli/package.standalone.json b/cli/package.standalone.json
new file mode 100644
index 000000000..aacd040dc
--- /dev/null
+++ b/cli/package.standalone.json
@@ -0,0 +1,32 @@
+{
+ "name": "protobufjs-cli",
+ "description": "Translates between file formats and generates static code as well as TypeScript definitions.",
+ "version": "6.7.0",
+ "author": "Daniel Wirtz ",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/dcodeIO/protobuf.js.git"
+ },
+ "license": "BSD-3-Clause",
+ "main": "index.js",
+ "types": "index.d.ts",
+ "bin": {
+ "pbjs": "bin/pbjs",
+ "pbts": "bin/pbts"
+ },
+ "peerDependencies": {
+ "protobufjs": "~6.7.0"
+ },
+ "dependencies": {
+ "chalk": "^1.1.3",
+ "escodegen": "^1.8.1",
+ "espree": "^3.1.3",
+ "estraverse": "^4.2.0",
+ "glob": "^7.1.1",
+ "jsdoc": "^3.4.2",
+ "minimist": "^1.2.0",
+ "semver": "^5.3.0",
+ "tmp": "0.0.31",
+ "uglify-js": "^2.8.15"
+ }
+}
\ No newline at end of file
diff --git a/cli/pbjs.js b/cli/pbjs.js
index b062125bd..553467613 100644
--- a/cli/pbjs.js
+++ b/cli/pbjs.js
@@ -1,12 +1,12 @@
"use strict";
var path = require("path"),
fs = require("fs"),
- pkg = require(path.join(__dirname, "package.json")),
+ pkg = require("./package.json"),
util = require("./util");
util.setup();
-var protobuf = require(".."),
+var protobuf = require(util.pathToProtobufJs),
minimist = require("minimist"),
chalk = require("chalk"),
glob = require("glob");
@@ -66,7 +66,7 @@ exports.main = function main(args, callback) {
process.stderr.write([
"protobuf.js v" + pkg.version + " CLI for JavaScript",
"",
- chalk.bold.white("Consolidates imports and converts between file formats."),
+ chalk.bold.white("Translates between file formats and generates static code."),
"",
" -t, --target Specifies the target format. Also accepts a path to require a custom target.",
"",
diff --git a/cli/pbts.js b/cli/pbts.js
index 68b6c501e..e47571668 100644
--- a/cli/pbts.js
+++ b/cli/pbts.js
@@ -2,7 +2,7 @@
var child_process = require("child_process"),
path = require("path"),
fs = require("fs"),
- pkg = require(path.join(__dirname, "./package.json")),
+ pkg = require("./package.json"),
util = require("./util");
util.setup();
diff --git a/cli/util.js b/cli/util.js
index 389302331..294e7e0ad 100644
--- a/cli/util.js
+++ b/cli/util.js
@@ -5,7 +5,16 @@ var fs = require("fs"),
var semver;
-var protobuf = require("..");
+try {
+ // installed as a peer dependency
+ require.resolve("protobufjs");
+ exports.pathToProtobufJs = "protobufjs";
+} catch (e) {
+ // local development, i.e. forked from github
+ exports.pathToProtobufJs = "..";
+}
+
+var protobuf = require(exports.pathToProtobufJs);
function basenameCompare(a, b) {
var aa = String(a).replace(/\.\w+$/, "").split(/(-?\d*\.?\d+)/g),