Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
protobufjs-cli
Advanced tools
Translates between file formats and generates static code as well as TypeScript definitions.
The protobufjs-cli package is a command-line interface for Protobuf.js, which provides a collection of tools to compile, inspect, and manage .proto files and their corresponding JavaScript code. It allows users to generate static code, JSON descriptors, and TypeScript definitions from .proto files, as well as to encode and decode messages using the Protocol Buffers binary format.
Compile .proto files to static JavaScript
This command compiles a .proto file into a static JavaScript module that can be used with CommonJS module systems. The output is written to 'compiled.js'.
pbjs -t static-module -w commonjs -o compiled.js file.proto
Generate JSON descriptors from .proto files
This command generates a JSON descriptor from a .proto file. The JSON output, which describes the message types and services, is written to 'descriptors.json'.
pbjs -t json -o descriptors.json file.proto
Generate TypeScript definitions from .proto files
This command generates TypeScript definitions from a compiled JavaScript file (generated by pbjs). The TypeScript definitions are written to 'types.d.ts'.
pbts -o types.d.ts compiled.js
Encode a message to the Protocol Buffers binary format
This command first compiles the .proto file to a static module and then encodes a message of type 'MessageName' with the provided field values to the Protocol Buffers binary format.
pbjs -t static-module file.proto | pbjs -p file.proto -e MessageName '{"field": "value"}'
Decode a message from the Protocol Buffers binary format
This command first compiles the .proto file to a static module and then decodes a message of type 'MessageName' from the Protocol Buffers binary format.
pbjs -t static-module file.proto | pbjs -p file.proto -d MessageName < encoded-message.bin
The google-protobuf package provides Protocol Buffers support for JavaScript. It includes a runtime library and a code generator to compile .proto files to JavaScript. It is similar to protobufjs-cli but is the official Google implementation and may have better support for the latest Protocol Buffers features.
grpc-tools is a Node.js package that includes the Protocol Buffers compiler (protoc) and the gRPC Node.js plugin. It is used to generate gRPC service code from .proto files. While it also deals with .proto files, its primary focus is on gRPC services rather than general Protocol Buffers message encoding and decoding.
Command line interface (CLI) for protobuf.js.
This can be used to translate between file formats and to generate static code as well as TypeScript definitions.
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 (non-functional on its own)
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.
--sparse Exports only those types referenced from a main file (experimental).
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)
closure A closure adding to protobuf.roots where protobuf is a global
-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.
--no-service Does not output service classes.
--force-long Enforces the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
--force-number Enforces the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
--force-message Enforces the use of message instances instead of plain objects.
--null-defaults Default value for optional fields is null instead of zero value.
--null-semantics Make nullable fields match protobuf semantics (overrides --null-defaults).
usage: pbjs [options] file1.proto file2.json ... (or pipe) 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:
var root = protobuf.Root.fromJSON(require("./bundle.json"));
or load it the usual way:
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.
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 only 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:
new SomeMessage(...)
, always use SomeMessage.create(...)
because reflection objects do not provide a constructor.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 -
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 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.
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.
Source | Library | Advantages | Tradeoffs |
---|---|---|---|
.proto | full | Easily editable Interoperability with other libraries No compile step | Some parsing and possibly network overhead |
JSON | light | Easily editable No parsing overhead Single bundle (no network overhead) | protobuf.js specific Has a compile step |
static | minimal | Works where eval access is restrictedFully documented Small footprint for small protos | Can be hard to edit No reflection Has a compile step |
Both utilities can be used programmatically by providing command line arguments and a callback to their respective main
functions:
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
FAQs
Translates between file formats and generates static code as well as TypeScript definitions.
The npm package protobufjs-cli receives a total of 936,668 weekly downloads. As such, protobufjs-cli popularity was classified as popular.
We found that protobufjs-cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.