protoc-plugin-js
v0.5.2
Published
`protoc` plugin generating minimal JS codecs with typings and a focus on small bundle size
Downloads
177
Readme
protoc-plugin-js
protoc
plugin generating minimal JS codecs with typings and a focus on small bundle size
Example
protoc \
--plugin=protoc-gen-js="$(npm bin)/protoc-plugin-js" \
--js_out="./build" \
-I "vega/protos/sources" \
vega/commands/v1/transaction.proto
Main Ideas
Each package, namespace, message and enum is split into separate files to help tree-shaking and minimise the final bundle size, if the user imports only the messages needed. Generated files are CommonJS, as that's the only format thats both compabitle with CommonJS and ESM consumers.
All field names are transformed into their "JSON" form by protoc
,
eg. my_field
in protobuf will be myField
in JS.
Currently merging of field is not supported.
Encoding
Falsy values are not encoded as they coincide with default values in protobuf,
with the exception of repeated
elements, which are checked against the length
of a possible array.
Unrecognised properties are not encoded as no mapping exists from an unknown
key to a fieldNumber
.
oneof
s are namespaced under the name of the oneof
, eg.
message Example {
oneof pick {
uint32 before = 1;
uint32 after = 2;
}
}
can be set as { pick: { before: 2000 } }
or { pick: { after: 2000 } }
.
{ pick: {} }
will encode to nothing, as none of the fields in the oneof
are given.
As a fallback for how most golang proto-to-JSON marshallers work, you can also give after: 2000
for the encoding direction, however the encoder will always prefer the more specific .pick.after
.
Types
tag
is encoded as a pair offieldNumber
andwireType
.fieldNumber
can be at most 29 bitsbytes
andstring
are defined in the spec to be at most 2GB, however that is not validated currentlyuint64
,int64
,uint32
andint32
can be both encoded asvarint
andfixed{32,64}
. This library encodes them asvarint
currently- While not entirely clear in the spec,
varint
will encode up to 64 bits, even if the format could encode arbitrary size numbers optional
values and unusedoneof
s are decoded asnull
to distinguish them fromundefined
fields, as "explicit presence"
Decoding
Decoding is done in three steps:
- A
reader
will iterate over the full protobuf message, emitting akey
/value
pair for eachtag
encountered value
s are decoded based on theirwireType
into one ofvarint
,bytes
,fixed64
orfixed32
- The compiled decoder will switch based on the
fieldNumber
and apply a "view" based on thetype
given in the protobuf message file, eg.string
will decode abytes
into a JS string,sint64
will decode avarint
and apply zig-zag decoding into a JSBigInt
Unknown fields and duplicate fields will still go through step 1 and 2, but may be discarded or overwrite a previous field in step 3.
Nested messages default to {}
(empty object) since