Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
The ts-proto npm package is a TypeScript code generator for Protocol Buffers (protobufs). It allows you to generate TypeScript types and client code from .proto files, making it easier to work with protobufs in TypeScript projects.
Generate TypeScript Types
This feature allows you to generate TypeScript types from your .proto files. The generated types can be used in your TypeScript code to ensure type safety when working with protobuf messages.
protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. your_proto_file.proto
Generate gRPC Client Code
This feature generates gRPC client code for your .proto files. The generated client code can be used to make gRPC calls from your TypeScript code.
protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. --ts_proto_opt=outputServices=grpc-js your_proto_file.proto
Generate JSON Serialization Code
This feature generates JSON serialization and deserialization methods for your protobuf messages. This is useful for converting protobuf messages to and from JSON format.
protoc --plugin=protoc-gen-ts_proto=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. --ts_proto_opt=outputJsonMethods=true your_proto_file.proto
protobufjs is a popular library for working with Protocol Buffers in JavaScript and TypeScript. It provides a runtime library for parsing and serializing protobuf messages, as well as a code generator for generating TypeScript definitions. Unlike ts-proto, protobufjs does not generate gRPC client code.
grpc-tools is a package that provides the protoc compiler and gRPC plugins for generating gRPC client and server code. It supports multiple languages, including JavaScript and TypeScript. However, grpc-tools does not generate TypeScript types directly from .proto files, which is a key feature of ts-proto.
grpc-web is a JavaScript implementation of gRPC for browser clients. It allows you to use gRPC in web applications. While grpc-web focuses on enabling gRPC in the browser, ts-proto focuses on generating TypeScript types and client code for Node.js and browser environments.
npm install ts-proto
protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./simple.proto
If you want to package the ts-proto
output into npm package to distribute to clients, run tsc
to generate the .d.ts
files (i.e. unlike pbjs/pbts, ts-proto
creates *.ts
files which can then directly be used/compiled by tsc
.)
ts-proto
is a clean break from either the built-in Google/Java-esque JS of protoc
and protobufjs
protobufjs/minimal
package is used for actually reading/writing bytes.)*.proto
-to-*.ts
workflow, currently no runtime reflection/loading of dynamic .proto
filesThe generated types are "just data", i.e.:
export interface Simple {
name: string;
age: number;
createdAt: Date | undefined;
child: Child | undefined;
state: StateEnum;
grandChildren: Child[];
coins: number[];
}
Along with encode
/decode
factory methods:
export const Simple = {
encode(message: Simple, writer: Writer = Writer.create()): Writer {
...
},
decode(reader: Reader, length?: number): Simple {
...
},
fromJSON(object: any): Simple {
...
},
fromPartial(object: DeepPartial<Simple>): Simple {
...
},
toJSON(message: Simple): unknown {
...
},
};
This allows idiomatic TS/JS usage like:
const bytes = Simple.encode({ name: ..., age: ..., ... }).finish();
const simple = Simple.decode(Reader.create(bytes));
const { name, age } = simple;
Which can dramatically ease integration when converting to/from other layers without creating a class and calling the right getters/setters.
A poor man's attempt at "please give us back optional types"
Wrapper types, i.e. google.protobuf.StringValue
, are mapped as optional values,
i.e. string | undefined
, which means for primitives we can kind of pretend that
the protobuf type system has optional types.
Timestamp is mapped as Date
fromJSON
/toJSON
support the canonical Protobuf JS format (i.e. timestamps are ISO strings)
ts-proto
is a protoc
plugin, so you run it by (either directly in your project, or more likely in your mono-repo schema pipeline, i.e. this or this):
ts-proto
to your package.json
npm install
to download itprotoc
with a plugin
parameter like:protoc --plugin=node_modules/ts-proto/protoc-gen-ts_proto ./batching.proto -I.
Supported options:
ts-proto
always generates Twirp service implementations for any RPC services, simply because that is what we use. Adding an option to disable Twirp and support GRPC is on the todo list.--ts_proto_opt=context=true
, the Twirp services will have a Go-style ctx
parameter, which is useful for tracing/logging/etc. if you're not using node's async_hooks
api due to performance reasons.Number.MAX_SAFE_INTEGER
blow up at runtimefromJSON
/toJSON
fromJSON
/toJSON
json_name
annotationkey=undefined
would subvert the approachCurrently fields that are modeled with oneof either_field { string field_a; string field_b }
are generated as field_a: string | undefined; field_b: string | undefined
.
This means you'll have to check if object.field_a
and if object.field_b
, and if you set one, you'll have to remember to unset the other.
It would be nice/preferable to model this as an ADT, so it would be:
object.either_field = { kind: 'field_a', value: 'name' };
However this differs sufficiently from the wire-level format that there might be wrinkles.
An original design notion of ts-proto
was that ideally we could get JSON off the wire and immediately cast it to the generated ts-proto
types, but features like oneof ADTs require walking the JSON looking for things to massage.
Similarily, writing a ts-proto
object as protobuf-compliant JSON would not be a straight JSON.stringify(tsProtoObject)
.
(Idea: maybe either_field
exists in the prototype, and wraps/manages the underlying primitive values.)
Protobuf has the somewhat annoying behavior that primitives types cannot differentiate between set-to-defalut-value and unset.
I.e. if you have a string name = 1
, and set object.name = ''
, Protobuf will skip sending the tagged name
field over the wire, because its understood that readers on the other end will, when they see name
is not included in the payload, return empty string.
ts-proto
models this behavior, of "unset" values being the primitive's default. (Technically by setting up an object prototype that knows the default values of the message's primitive fields.)
If you want fields where you can model set/unset, see Wrapper Types.
In core Protobuf, while unset primitives are read as default values, unset messages are returned as null
.
This allows a cute hack where you can model a logical string | null
by creating a field that is a message (can be null) and the message has a single string value (for when the value is not null).
Protobuf has several built-in types for this pattern, i.e. google.protobuf.StringValue
.
ts-proto
understands these wrapper types and will generate google.protobuf.StringValue name = 1
as a name: string | undefined
.
This hides some of the StringValue
mess and gives a more idiomatic way of using them.
Granted, it's unfortunate this is not as simple as marking the string
as optional
.
string name = 1
.StringValue name = 1
.SubMessage message = 1
.FAQs
[![npm](https://img.shields.io/npm/v/ts-proto)](https://www.npmjs.com/package/ts-proto) [![build](https://github.com/stephenh/ts-proto/workflows/Build/badge.svg)](https://github.com/stephenh/ts-proto/actions)
The npm package ts-proto receives a total of 362,162 weekly downloads. As such, ts-proto popularity was classified as popular.
We found that ts-proto demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 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.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.