protobufjs 8.1.6-experimental → 8.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -570
- package/dist/light/protobuf.js +2041 -1482
- package/dist/light/protobuf.js.map +1 -1
- package/dist/light/protobuf.min.js +3 -3
- package/dist/light/protobuf.min.js.map +1 -1
- package/dist/minimal/protobuf.js +1167 -863
- package/dist/minimal/protobuf.js.map +1 -1
- package/dist/minimal/protobuf.min.js +3 -3
- package/dist/minimal/protobuf.min.js.map +1 -1
- package/dist/protobuf.js +2173 -1527
- package/dist/protobuf.js.map +1 -1
- package/dist/protobuf.min.js +3 -3
- package/dist/protobuf.min.js.map +1 -1
- package/ext/README.md +81 -0
- package/ext/descriptor/README.md +3 -70
- package/ext/descriptor/index.d.ts +1 -190
- package/ext/descriptor/index.js +1 -1161
- package/ext/descriptor.d.ts +309 -0
- package/ext/descriptor.js +1241 -0
- package/ext/textformat.d.ts +24 -0
- package/ext/textformat.js +1227 -0
- package/google/protobuf/compiler/plugin.json +126 -0
- package/google/protobuf/compiler/plugin.proto +47 -0
- package/google/protobuf/descriptor.json +2 -2
- package/google/protobuf/descriptor.proto +2 -1
- package/index.d.ts +585 -476
- package/package.json +22 -40
- package/src/converter.js +63 -27
- package/src/decoder.js +126 -49
- package/src/encoder.js +10 -2
- package/src/enum.js +4 -1
- package/src/field.js +10 -7
- package/src/mapfield.js +1 -0
- package/src/message.js +7 -6
- package/src/method.js +4 -3
- package/src/namespace.js +31 -12
- package/src/object.js +24 -19
- package/src/oneof.js +2 -0
- package/src/parse.js +128 -46
- package/src/reader.js +145 -30
- package/src/reader_buffer.js +24 -3
- package/src/root.js +10 -4
- package/src/service.js +15 -6
- package/src/tokenize.js +6 -1
- package/src/type.js +57 -27
- package/src/types.js +1 -1
- package/src/util/aspromise.d.ts +13 -0
- package/src/util/aspromise.js +52 -0
- package/src/util/base64.d.ts +32 -0
- package/src/util/base64.js +146 -0
- package/src/util/codegen.d.ts +31 -0
- package/src/util/codegen.js +113 -0
- package/src/util/eventemitter.d.ts +45 -0
- package/src/util/eventemitter.js +84 -0
- package/src/util/fetch.d.ts +56 -0
- package/src/util/fetch.js +112 -0
- package/src/util/float.d.ts +83 -0
- package/src/util/float.js +335 -0
- package/src/util/fs.js +11 -0
- package/src/util/inquire.d.ts +10 -0
- package/src/util/inquire.js +38 -0
- package/src/util/minimal.js +74 -12
- package/src/util/path.d.ts +22 -0
- package/src/util/path.js +72 -0
- package/src/util/patterns.js +8 -0
- package/src/util/pool.d.ts +32 -0
- package/src/util/pool.js +48 -0
- package/src/util/utf8.d.ts +24 -0
- package/src/util/utf8.js +130 -0
- package/src/util.js +18 -13
- package/src/verifier.js +7 -4
- package/src/wrappers.js +4 -3
- package/src/writer.js +33 -5
- package/src/writer_buffer.js +18 -1
- package/tsconfig.json +2 -2
- package/ext/descriptor/test.js +0 -54
package/README.md
CHANGED
|
@@ -9,719 +9,374 @@
|
|
|
9
9
|
|
|
10
10
|
**Protocol Buffers** are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google ([see](https://protobuf.dev/)).
|
|
11
11
|
|
|
12
|
-
**protobuf.js** is a
|
|
12
|
+
**protobuf.js** is a standalone JavaScript implementation of Protocol Buffers with TypeScript support for Node.js and the browser. It works with `.proto` files out of the box, is optimized for fast binary I/O, and supports runtime reflection as well as static code generation.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
--------
|
|
14
|
+
## Getting started
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
How to include protobuf.js in your project.
|
|
19
|
-
|
|
20
|
-
* [Usage](#usage)<br />
|
|
21
|
-
A brief introduction to using the toolset.
|
|
22
|
-
|
|
23
|
-
* [Valid Message](#valid-message)
|
|
24
|
-
* [Toolset](#toolset)<br />
|
|
25
|
-
|
|
26
|
-
* [Examples](#examples)<br />
|
|
27
|
-
A few examples to get you started.
|
|
28
|
-
|
|
29
|
-
* [Using .proto files](#using-proto-files)
|
|
30
|
-
* [Using JSON descriptors](#using-json-descriptors)
|
|
31
|
-
* [Using reflection only](#using-reflection-only)
|
|
32
|
-
* [Using custom classes](#using-custom-classes)
|
|
33
|
-
* [Using services](#using-services)
|
|
34
|
-
* [Usage with TypeScript](#usage-with-typescript)<br />
|
|
35
|
-
|
|
36
|
-
* [Additional documentation](#additional-documentation)<br />
|
|
37
|
-
A list of available documentation resources.
|
|
38
|
-
|
|
39
|
-
* [Performance](#performance)<br />
|
|
40
|
-
A few internals and a benchmark on performance.
|
|
41
|
-
|
|
42
|
-
* [Compatibility](#compatibility)<br />
|
|
43
|
-
Notes on compatibility regarding browsers and optional libraries.
|
|
44
|
-
|
|
45
|
-
* [Building](#building)<br />
|
|
46
|
-
How to build the library and its components yourself.
|
|
47
|
-
|
|
48
|
-
Installation
|
|
49
|
-
---------------
|
|
50
|
-
|
|
51
|
-
### Node.js
|
|
16
|
+
### Install
|
|
52
17
|
|
|
53
18
|
```sh
|
|
54
|
-
npm install protobufjs
|
|
19
|
+
npm install protobufjs
|
|
55
20
|
```
|
|
56
21
|
|
|
57
|
-
|
|
58
|
-
// Static code + Reflection + .proto parser
|
|
59
|
-
var protobuf = require("protobufjs");
|
|
60
|
-
|
|
61
|
-
// Static code + Reflection
|
|
62
|
-
var protobuf = require("protobufjs/light");
|
|
63
|
-
|
|
64
|
-
// Static code only
|
|
65
|
-
var protobuf = require("protobufjs/minimal");
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
The optional [command line utility](./cli/) to generate static code and reflection bundles lives in the `protobufjs-cli` package and can be installed separately:
|
|
22
|
+
The [command line utility](./cli/) for generating reflection bundles, static code and TypeScript declarations is published as an add-on package:
|
|
69
23
|
|
|
70
24
|
```sh
|
|
71
|
-
npm install
|
|
25
|
+
npm install --save-dev protobufjs-cli
|
|
72
26
|
```
|
|
73
27
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
Pick the variant matching your needs and replace the version tag with the exact [release](https://github.com/protobufjs/protobuf.js/tags) your project depends upon. For example, to use the minified full variant:
|
|
77
|
-
|
|
78
|
-
```html
|
|
79
|
-
<script src="//cdn.jsdelivr.net/npm/protobufjs@7.X.X/dist/protobuf.min.js"></script>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
| Distribution | Location
|
|
83
|
-
|--------------|--------------------------------------------------------
|
|
84
|
-
| Full | <https://cdn.jsdelivr.net/npm/protobufjs/dist/>
|
|
85
|
-
| Light | <https://cdn.jsdelivr.net/npm/protobufjs/dist/light/>
|
|
86
|
-
| Minimal | <https://cdn.jsdelivr.net/npm/protobufjs/dist/minimal/>
|
|
87
|
-
|
|
88
|
-
All variants support CommonJS and AMD loaders and export globally as `window.protobuf`.
|
|
89
|
-
|
|
90
|
-
Usage
|
|
91
|
-
-----
|
|
92
|
-
|
|
93
|
-
Because JavaScript is a dynamically typed language, protobuf.js utilizes the concept of a **valid message** in order to provide the best possible [performance](#performance) (and, as a side product, proper typings):
|
|
94
|
-
|
|
95
|
-
### Valid message
|
|
96
|
-
|
|
97
|
-
> A valid message is an object (1) not missing any required fields and (2) exclusively composed of JS types understood by the wire format writer.
|
|
98
|
-
|
|
99
|
-
There are two possible types of valid messages and the encoder is able to work with both of these for convenience:
|
|
100
|
-
|
|
101
|
-
* **Message instances** (explicit instances of message classes with default values on their prototype) naturally satisfy the requirements of a valid message and
|
|
102
|
-
* **Plain JavaScript objects** that just so happen to be composed in a way satisfying the requirements of a valid message as well.
|
|
103
|
-
|
|
104
|
-
In a nutshell, the wire format writer understands the following types:
|
|
105
|
-
|
|
106
|
-
| Field type | Expected JS type (create, encode) | Conversion (fromObject)
|
|
107
|
-
|------------|-----------------------------------|------------------------
|
|
108
|
-
| s-/u-/int32<br />s-/fixed32 | `number` (32 bit integer) | <code>value | 0</code> if signed<br />`value >>> 0` if unsigned
|
|
109
|
-
| s-/u-/int64<br />s-/fixed64 | `Long`-like (optimal)<br />`number` (53 bit integer) | `Long.fromValue(value)` with long.js<br />`parseInt(value, 10)` otherwise
|
|
110
|
-
| float<br />double | `number` | `Number(value)`
|
|
111
|
-
| bool | `boolean` | `Boolean(value)`
|
|
112
|
-
| string | `string` | `String(value)`
|
|
113
|
-
| bytes | `Uint8Array` (optimal)<br />`Buffer` (optimal under node)<br />`Array.<number>` (8 bit integers) | `base64.decode(value)` if a `string`<br />`Object` with non-zero `.length` is assumed to be buffer-like
|
|
114
|
-
| enum | `number` (32 bit integer) | Looks up the numeric id if a `string`
|
|
115
|
-
| message | Valid message | `Message.fromObject(value)`
|
|
116
|
-
| repeated T | `Array<T>` | Copy
|
|
117
|
-
| map<K, V> | `Object<K,V>` | Copy
|
|
118
|
-
|
|
119
|
-
* Explicit `undefined` and `null` are considered as not set if the field is optional.
|
|
120
|
-
* Maps are objects where the key is the string representation of the respective value or an 8 characters long hash string for `Long`-likes.
|
|
121
|
-
|
|
122
|
-
### Toolset
|
|
123
|
-
|
|
124
|
-
With that in mind and again for performance reasons, each message class provides a distinct set of methods with each method doing just one thing. This avoids unnecessary assertions / redundant operations where performance is a concern but also forces a user to perform verification (of plain JavaScript objects that *might* just so happen to be a valid message) explicitly where necessary - for example when dealing with user input.
|
|
125
|
-
|
|
126
|
-
**Note** that `Message` below refers to any message class.
|
|
127
|
-
|
|
128
|
-
* **Message.verify**(message: `Object`): `null|string`<br />
|
|
129
|
-
verifies that a **plain JavaScript object** satisfies the requirements of a valid message and thus can be encoded without issues. Instead of throwing, it returns the error message as a string, if any.
|
|
130
|
-
|
|
131
|
-
```js
|
|
132
|
-
var payload = "invalid (not an object)";
|
|
133
|
-
var err = AwesomeMessage.verify(payload);
|
|
134
|
-
if (err)
|
|
135
|
-
throw Error(err);
|
|
136
|
-
```
|
|
28
|
+
The CLI is a small but capable standalone protobuf.js toolchain. It does not require `protoc` or a language plugin.
|
|
137
29
|
|
|
138
|
-
|
|
139
|
-
encodes a **message instance** or valid **plain JavaScript object**. This method does not implicitly verify the message and it's up to the user to make sure that the payload is a valid message.
|
|
30
|
+
### Choose a runtime
|
|
140
31
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
32
|
+
| Import | Includes | Use when
|
|
33
|
+
| ----------------------- | ------------------ | --------
|
|
34
|
+
| `protobufjs` | Reflection, Parser | You load `.proto` files at runtime
|
|
35
|
+
| `protobufjs/light.js` | Reflection | You load JSON bundles or build schemas programmatically
|
|
36
|
+
| `protobufjs/minimal.js` | Static runtime | You only use generated static code
|
|
144
37
|
|
|
145
|
-
|
|
146
|
-
works like `Message.encode` but additionally prepends the length of the message as a varint.
|
|
38
|
+
The full build includes the light build, and the light build includes the minimal runtime.
|
|
147
39
|
|
|
148
|
-
|
|
149
|
-
decodes a buffer to a **message instance**. If required fields are missing, it throws a `util.ProtocolError` with an `instance` property set to the so far decoded message. If the wire format is invalid, it throws an `Error`.
|
|
40
|
+
### Browser builds
|
|
150
41
|
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
var decodedMessage = AwesomeMessage.decode(buffer);
|
|
154
|
-
} catch (e) {
|
|
155
|
-
if (e instanceof protobuf.util.ProtocolError) {
|
|
156
|
-
// e.instance holds the so far decoded message with missing required fields
|
|
157
|
-
} else {
|
|
158
|
-
// wire format is invalid
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
```
|
|
42
|
+
Pick the distribution matching your runtime variant and pin an exact version:
|
|
162
43
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
* **Message.fromObject**(object: `Object`): `Message`<br />
|
|
174
|
-
converts any non-valid **plain JavaScript object** to a **message instance** using the conversion steps outlined within the table above.
|
|
175
|
-
|
|
176
|
-
```js
|
|
177
|
-
var message = AwesomeMessage.fromObject({ awesomeField: 42 });
|
|
178
|
-
// converts awesomeField to a string
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
* **Message.toObject**(message: `Message` [, options: `ConversionOptions`]): `Object`<br />
|
|
182
|
-
converts a **message instance** to an arbitrary **plain JavaScript object** for interoperability with other libraries or storage. The resulting plain JavaScript object *might* still satisfy the requirements of a valid message depending on the actual conversion options specified, but most of the time it does not.
|
|
183
|
-
|
|
184
|
-
```js
|
|
185
|
-
var object = AwesomeMessage.toObject(message, {
|
|
186
|
-
enums: String, // enums as string names
|
|
187
|
-
longs: String, // longs as strings (requires long.js)
|
|
188
|
-
bytes: String, // bytes as base64 encoded strings
|
|
189
|
-
defaults: true, // includes default values
|
|
190
|
-
arrays: true, // populates empty arrays (repeated fields) even if defaults=false
|
|
191
|
-
objects: true, // populates empty objects (map fields) even if defaults=false
|
|
192
|
-
oneofs: true // includes virtual oneof fields set to the present field's name
|
|
193
|
-
});
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
For reference, the following diagram aims to display relationships between the different methods and the concept of a valid message:
|
|
44
|
+
```html
|
|
45
|
+
<!-- Full -->
|
|
46
|
+
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/protobuf.min.js"></script>
|
|
47
|
+
<!-- Light -->
|
|
48
|
+
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/light/protobuf.min.js"></script>
|
|
49
|
+
<!-- Minimal -->
|
|
50
|
+
<script src="https://cdn.jsdelivr.net/npm/protobufjs@8.X.X/dist/minimal/protobuf.min.js"></script>
|
|
51
|
+
```
|
|
197
52
|
|
|
198
|
-
|
|
53
|
+
Browser builds support CommonJS and AMD loaders and export globally as `window.protobuf`.
|
|
199
54
|
|
|
200
|
-
|
|
55
|
+
## Usage
|
|
201
56
|
|
|
202
|
-
|
|
203
|
-
--------
|
|
57
|
+
The examples below use this schema:
|
|
204
58
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
It is possible to load existing .proto files using the full library, which parses and compiles the definitions to ready to use (reflection-based) message classes:
|
|
59
|
+
```proto
|
|
60
|
+
syntax = "proto3";
|
|
208
61
|
|
|
209
|
-
```protobuf
|
|
210
|
-
// awesome.proto
|
|
211
62
|
package awesomepackage;
|
|
212
|
-
syntax = "proto3";
|
|
213
63
|
|
|
214
64
|
message AwesomeMessage {
|
|
215
|
-
|
|
65
|
+
string awesome_field = 1;
|
|
216
66
|
}
|
|
217
67
|
```
|
|
218
68
|
|
|
219
|
-
|
|
220
|
-
protobuf.load("awesome.proto", function(err, root) {
|
|
221
|
-
if (err)
|
|
222
|
-
throw err;
|
|
223
|
-
|
|
224
|
-
// Obtain a message type
|
|
225
|
-
var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
|
|
226
|
-
|
|
227
|
-
// Exemplary payload
|
|
228
|
-
var payload = { awesomeField: "AwesomeString" };
|
|
69
|
+
protobuf.js converts `.proto` field names to camelCase by default, so `awesome_field` is used as `awesomeField` in JavaScript. Use the `keepCase` option when loading or parsing `.proto` files to preserve field names as written.
|
|
229
70
|
|
|
230
|
-
|
|
231
|
-
var errMsg = AwesomeMessage.verify(payload);
|
|
232
|
-
if (errMsg)
|
|
233
|
-
throw Error(errMsg);
|
|
71
|
+
### Load a schema
|
|
234
72
|
|
|
235
|
-
|
|
236
|
-
|
|
73
|
+
```js
|
|
74
|
+
const protobuf = require("protobufjs");
|
|
237
75
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
76
|
+
const root = protobuf.loadSync("awesome.proto");
|
|
77
|
+
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
|
|
78
|
+
```
|
|
241
79
|
|
|
242
|
-
|
|
243
|
-
var message = AwesomeMessage.decode(buffer);
|
|
244
|
-
// ... do something with message
|
|
80
|
+
Use `protobuf.load()` for the asynchronous variant.
|
|
245
81
|
|
|
246
|
-
|
|
82
|
+
### Encode and decode
|
|
247
83
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
longs: String,
|
|
251
|
-
enums: String,
|
|
252
|
-
bytes: String,
|
|
253
|
-
// see ConversionOptions
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
```
|
|
84
|
+
```js
|
|
85
|
+
const payload = { awesomeField: "hello" };
|
|
257
86
|
|
|
258
|
-
|
|
87
|
+
// Optionally verify if the payload is of uncertain shape
|
|
88
|
+
const err = AwesomeMessage.verify(payload);
|
|
89
|
+
if (err) throw Error(err);
|
|
259
90
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
.then(function(root) {
|
|
263
|
-
...
|
|
264
|
-
});
|
|
265
|
-
```
|
|
91
|
+
// Optionally create a message instance from already valid data
|
|
92
|
+
const message = AwesomeMessage.create(payload);
|
|
266
93
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
The library utilizes JSON descriptors that are equivalent to a .proto definition. For example, the following is identical to the .proto definition seen above:
|
|
270
|
-
|
|
271
|
-
```json
|
|
272
|
-
// awesome.json
|
|
273
|
-
{
|
|
274
|
-
"nested": {
|
|
275
|
-
"awesomepackage": {
|
|
276
|
-
"nested": {
|
|
277
|
-
"AwesomeMessage": {
|
|
278
|
-
"fields": {
|
|
279
|
-
"awesomeField": {
|
|
280
|
-
"type": "string",
|
|
281
|
-
"id": 1
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
94
|
+
const encoded = AwesomeMessage.encode(message).finish();
|
|
95
|
+
const decoded = AwesomeMessage.decode(encoded);
|
|
289
96
|
```
|
|
290
97
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
| Type (T) | Extends | Type-specific properties
|
|
294
|
-
|--------------------|--------------------|-------------------------
|
|
295
|
-
| *ReflectionObject* | | options
|
|
296
|
-
| *Namespace* | *ReflectionObject* | nested
|
|
297
|
-
| Root | *Namespace* | **nested**
|
|
298
|
-
| Type | *Namespace* | **fields**
|
|
299
|
-
| Enum | *ReflectionObject* | **values**
|
|
300
|
-
| Field | *ReflectionObject* | rule, **type**, **id**
|
|
301
|
-
| MapField | Field | **keyType**
|
|
302
|
-
| OneOf | *ReflectionObject* | **oneof** (array of field names)
|
|
303
|
-
| Service | *Namespace* | **methods**
|
|
304
|
-
| Method | *ReflectionObject* | type, **requestType**, **responseType**, requestStream, responseStream
|
|
98
|
+
`encode` expects a message instance or equivalent plain object and does not verify input implicitly. Use `verify` for plain objects whose shape is not guaranteed, `create` to create a message instance from already valid data when useful, and `fromObject` when conversion from broader JavaScript input is needed.
|
|
305
99
|
|
|
306
|
-
|
|
307
|
-
* `T.fromJSON(name, json)` creates the respective reflection object from a JSON descriptor
|
|
308
|
-
* `T#toJSON()` creates a JSON descriptor from the respective reflection object (its name is used as the key within the parent)
|
|
100
|
+
Plain objects can be encoded directly when they already use protobuf.js runtime types: numbers for 32-bit numeric fields, booleans for `bool`, strings for `string`, `Uint8Array` or `Buffer` for `bytes`, arrays for repeated fields, and plain objects for maps. Map keys are the string representation of the respective value or an 8-character hash string for 64-bit/`Long` keys. Use `fromObject` when input may use broader JSON-style forms such as enum names, base64 strings for bytes, or decimal strings for 64-bit values.
|
|
309
101
|
|
|
310
|
-
|
|
102
|
+
Install [`long`](https://github.com/dcodeIO/long.js) with protobuf.js when exact 64-bit integer support is required.
|
|
311
103
|
|
|
312
|
-
|
|
104
|
+
### Convert plain objects
|
|
313
105
|
|
|
314
106
|
```js
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
107
|
+
const message = AwesomeMessage.fromObject({ awesomeField: 42 });
|
|
108
|
+
const object = AwesomeMessage.toObject(message, {
|
|
109
|
+
longs: String,
|
|
110
|
+
enums: String,
|
|
111
|
+
bytes: String
|
|
319
112
|
});
|
|
320
113
|
```
|
|
321
114
|
|
|
322
|
-
|
|
115
|
+
Common `ConversionOptions` are:
|
|
323
116
|
|
|
324
|
-
|
|
325
|
-
|
|
117
|
+
| Option | Effect |
|
|
118
|
+
|--------|--------|
|
|
119
|
+
| `longs: String` | Converts 64-bit values to decimal strings |
|
|
120
|
+
| `longs: Number` | Converts 64-bit values to JS numbers (may lose precision) |
|
|
121
|
+
| `enums: String` | Converts enum values to names |
|
|
122
|
+
| `bytes: String` | Converts bytes to base64 strings |
|
|
123
|
+
| `defaults: true` | Includes default values for unset fields |
|
|
124
|
+
| `arrays: true` | Includes empty arrays for repeated fields |
|
|
125
|
+
| `objects: true` | Includes empty objects for map fields |
|
|
126
|
+
| `oneofs: true` | Includes virtual oneof discriminator properties |
|
|
326
127
|
|
|
327
|
-
|
|
128
|
+
## Message API
|
|
328
129
|
|
|
329
|
-
|
|
330
|
-
```
|
|
130
|
+
Message types expose focused methods for validation, conversion, and binary I/O.
|
|
331
131
|
|
|
332
|
-
|
|
132
|
+
* **verify**(object: `object`): `null | string`
|
|
133
|
+
Checks whether a plain object can be encoded as-is. Returns `null` if valid, otherwise an error message.
|
|
333
134
|
|
|
334
|
-
|
|
135
|
+
* **create**(properties?: `object`): `Message`
|
|
136
|
+
Creates a message instance from already valid data.
|
|
335
137
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
var Root = protobuf.Root,
|
|
339
|
-
Type = protobuf.Type,
|
|
340
|
-
Field = protobuf.Field;
|
|
138
|
+
* **fromObject**(object: `object`): `Message`
|
|
139
|
+
Converts broader JavaScript input into a message instance.
|
|
341
140
|
|
|
342
|
-
|
|
141
|
+
* **toObject**(message: `Message`, options?: `ConversionOptions`): `object`
|
|
142
|
+
Converts a message instance to a plain object for JSON or interoperability.
|
|
343
143
|
|
|
344
|
-
|
|
144
|
+
* **encode**(message: `Message | object`, writer?: `Writer`): `Writer`
|
|
145
|
+
Encodes a message or equivalent plain object. Call `.finish()` on the returned writer to obtain a buffer.
|
|
345
146
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
Detailed information on the reflection structure is available within the [API documentation](#additional-documentation).
|
|
147
|
+
* **encodeDelimited**(message: `Message | object`, writer?: `Writer`): `Writer`
|
|
148
|
+
Encodes a length-delimited message.
|
|
351
149
|
|
|
352
|
-
|
|
150
|
+
* **decode**(reader: `Reader | Uint8Array`): `Message`
|
|
151
|
+
Decodes a message from protobuf binary data.
|
|
353
152
|
|
|
354
|
-
|
|
153
|
+
* **decodeDelimited**(reader: `Reader | Uint8Array`): `Message`
|
|
154
|
+
Decodes a length-delimited message.
|
|
355
155
|
|
|
356
|
-
|
|
357
|
-
|
|
156
|
+
* **message#toJSON**(): `object`
|
|
157
|
+
Converts a message instance to JSON-compatible output using default conversion options.
|
|
358
158
|
|
|
359
|
-
|
|
360
|
-
function AwesomeMessage(properties) {
|
|
361
|
-
// custom initialization code
|
|
362
|
-
...
|
|
363
|
-
}
|
|
159
|
+
Length-delimited methods read and write a varint byte length before the message, which is useful for streams and framed protocols.
|
|
364
160
|
|
|
365
|
-
|
|
366
|
-
root.lookupType("awesomepackage.AwesomeMessage").ctor = AwesomeMessage;
|
|
161
|
+
If required fields are missing while decoding proto2 data, `decode` throws `protobuf.util.ProtocolError` with the partially decoded message available as `err.instance`.
|
|
367
162
|
|
|
368
|
-
|
|
369
|
-
AwesomeMessage.customStaticMethod = function() { ... };
|
|
370
|
-
AwesomeMessage.prototype.customInstanceMethod = function() { ... };
|
|
163
|
+
## Code generation
|
|
371
164
|
|
|
372
|
-
|
|
373
|
-
```
|
|
165
|
+
Use [`protobufjs-cli`](./cli/) to generate reflection bundles, static JavaScript code and TypeScript declarations, either directly with `pbjs` or through its `protoc-gen-pbjs` plugin.
|
|
374
166
|
|
|
375
|
-
|
|
167
|
+
Reflection keeps schemas as descriptors and generates optimized functions at runtime. Static code emits the same optimized functions ahead of time. The main tradeoffs are how schemas are loaded, how bundle size scales with schema size, whether runtime code generation is allowed by your environment, and whether reflection metadata should remain available at runtime.
|
|
376
168
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
169
|
+
| Target | Output | Minimum Runtime |
|
|
170
|
+
|--------|--------|-----------------|
|
|
171
|
+
| `json` | JSON bundle | `protobufjs/light.js` |
|
|
172
|
+
| `json-module` | JSON bundle module | `protobufjs/light.js` |
|
|
173
|
+
| `static` | Static code | custom wrapper/integration, not standalone |
|
|
174
|
+
| `static-module` | Static code module | `protobufjs/minimal.js` |
|
|
382
175
|
|
|
383
|
-
|
|
176
|
+
Module targets support `--wrap default` for CommonJS and AMD, plus `commonjs`, `amd`, `esm`, and `closure`; `--wrap` can also load a custom wrapper module.
|
|
384
177
|
|
|
385
|
-
|
|
178
|
+
### Static modules
|
|
386
179
|
|
|
387
|
-
|
|
388
|
-
...
|
|
180
|
+
Static modules generate dedicated JavaScript code for your schema, so they only need `protobufjs/minimal.js`.
|
|
389
181
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
// Define custom functionality
|
|
394
|
-
AwesomeMessage.customStaticMethod = function() { ... };
|
|
395
|
-
AwesomeMessage.prototype.customInstanceMethod = function() { ... };
|
|
396
|
-
|
|
397
|
-
// Continue at "Create a new message" above
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
### Using services
|
|
401
|
-
|
|
402
|
-
The library also supports consuming services but it doesn't make any assumptions about the actual transport channel. Instead, a user must provide a suitable RPC implementation, which is an asynchronous function that takes the reflected service method, the binary request and a node-style callback as its parameters:
|
|
403
|
-
|
|
404
|
-
```js
|
|
405
|
-
function rpcImpl(method, requestData, callback) {
|
|
406
|
-
// perform the request using an HTTP request or a WebSocket for example
|
|
407
|
-
var responseData = ...;
|
|
408
|
-
// and call the callback with the binary response afterwards:
|
|
409
|
-
callback(null, responseData);
|
|
410
|
-
}
|
|
182
|
+
```sh
|
|
183
|
+
npx pbjs -t static-module -w esm -o awesome.js --dts awesome.proto
|
|
411
184
|
```
|
|
412
185
|
|
|
413
|
-
Below is a working example with a typescript implementation using grpc npm package.
|
|
414
186
|
```ts
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const
|
|
418
|
-
const client = new Client(
|
|
419
|
-
grpcServerUrl,
|
|
420
|
-
grpc.credentials.createInsecure()
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
const rpcImpl = function(method, requestData, callback) {
|
|
424
|
-
client.makeUnaryRequest(
|
|
425
|
-
method.name,
|
|
426
|
-
arg => arg,
|
|
427
|
-
arg => arg,
|
|
428
|
-
requestData,
|
|
429
|
-
callback
|
|
430
|
-
)
|
|
431
|
-
}
|
|
187
|
+
import { awesomepackage } from "./awesome.js";
|
|
188
|
+
|
|
189
|
+
const message = awesomepackage.AwesomeMessage.create({ awesomeField: "hello" });
|
|
432
190
|
```
|
|
433
191
|
|
|
434
|
-
|
|
192
|
+
### Reflection bundles
|
|
435
193
|
|
|
436
|
-
|
|
437
|
-
// greeter.proto
|
|
438
|
-
syntax = "proto3";
|
|
439
|
-
|
|
440
|
-
service Greeter {
|
|
441
|
-
rpc SayHello (HelloRequest) returns (HelloReply) {}
|
|
442
|
-
}
|
|
194
|
+
Bundling schemas avoids reparsing `.proto` files at runtime and can reduce browser requests when schemas would otherwise be loaded separately. While reflection requires at least `protobufjs/light.js`, large schemas often produce smaller bundles than equivalent static modules because most code is shared via reflection.
|
|
443
195
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
message HelloReply {
|
|
449
|
-
string message = 1;
|
|
450
|
-
}
|
|
196
|
+
```sh
|
|
197
|
+
npx pbjs -t json -o awesome.json awesome1.proto awesome2.proto ...
|
|
451
198
|
```
|
|
452
199
|
|
|
453
200
|
```js
|
|
454
|
-
|
|
455
|
-
var Greeter = root.lookup("Greeter");
|
|
456
|
-
var greeter = Greeter.create(/* see above */ rpcImpl, /* request delimited? */ false, /* response delimited? */ false);
|
|
201
|
+
const bundle = require("./awesome.json");
|
|
457
202
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
});
|
|
203
|
+
const root = protobuf.Root.fromJSON(bundle);
|
|
204
|
+
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
|
|
461
205
|
```
|
|
462
206
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
```js
|
|
466
|
-
greeter.sayHello({ name: 'you' })
|
|
467
|
-
.then(function(response) {
|
|
468
|
-
console.log('Greeting:', response.message);
|
|
469
|
-
});
|
|
207
|
+
```sh
|
|
208
|
+
npx pbjs -t json-module -w esm -o awesome.js --dts awesome.proto
|
|
470
209
|
```
|
|
471
210
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
Note that the service API is meant for clients. Implementing a server-side endpoint pretty much always requires transport channel (i.e. http, websocket, etc.) specific code with the only common denominator being that it decodes and encodes messages.
|
|
475
|
-
|
|
476
|
-
### Usage with TypeScript
|
|
211
|
+
```js
|
|
212
|
+
import { awesomepackage } from "./awesome.js";
|
|
477
213
|
|
|
478
|
-
|
|
214
|
+
const AwesomeMessage = awesomepackage.AwesomeMessage;
|
|
215
|
+
```
|
|
479
216
|
|
|
480
|
-
|
|
217
|
+
JSON modules export the reflection root and, with `-w esm`, also provide top-level named exports that align with static modules. Their declarations mirror `static-module` typings, but because JSON modules are backed by reflection objects, message instances should be created with `MyMessage.create(...)` instead of constructors. Code using `create(...)` works with static modules as well.
|
|
481
218
|
|
|
482
|
-
|
|
219
|
+
### TypeScript integration
|
|
483
220
|
|
|
484
|
-
|
|
221
|
+
TypeScript is a first-class target in protobuf.js. The runtime API is typed, and with `--dts`, both `json-module` and `static-module` emit ready-to-run JavaScript modules together with matching TypeScript declarations. No separate transpile step is necessary.
|
|
485
222
|
|
|
486
|
-
|
|
487
|
-
import { load } from "protobufjs"; // respectively "./node_modules/protobufjs"
|
|
223
|
+
## Advanced usage
|
|
488
224
|
|
|
489
|
-
|
|
490
|
-
if (err)
|
|
491
|
-
throw err;
|
|
225
|
+
### Programmatic schemas
|
|
492
226
|
|
|
493
|
-
|
|
494
|
-
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");
|
|
227
|
+
The full and light builds can construct schemas directly through reflection:
|
|
495
228
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
let buffer = AwesomeMessage.encode(message).finish();
|
|
500
|
-
console.log(`buffer = ${Array.prototype.toString.call(buffer)}`);
|
|
229
|
+
```js
|
|
230
|
+
const AwesomeMessage = new protobuf.Type("AwesomeMessage")
|
|
231
|
+
.add(new protobuf.Field("awesomeField", 1, "string"));
|
|
501
232
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
233
|
+
const root = new protobuf.Root()
|
|
234
|
+
.define("awesomepackage")
|
|
235
|
+
.add(AwesomeMessage);
|
|
505
236
|
```
|
|
506
237
|
|
|
507
|
-
|
|
238
|
+
### Custom message classes
|
|
508
239
|
|
|
509
|
-
|
|
240
|
+
Message classes can be extended by reusing the generated constructor:
|
|
510
241
|
|
|
511
|
-
```
|
|
512
|
-
|
|
242
|
+
```js
|
|
243
|
+
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage").ctor;
|
|
513
244
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
245
|
+
AwesomeMessage.customStaticMethod = function() {
|
|
246
|
+
// ...
|
|
247
|
+
};
|
|
248
|
+
AwesomeMessage.prototype.customInstanceMethod = function() {
|
|
249
|
+
// ...
|
|
250
|
+
};
|
|
518
251
|
```
|
|
519
252
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
The library also includes an early implementation of [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html).
|
|
523
|
-
|
|
524
|
-
**Note** that decorators are an experimental feature in TypeScript and that declaration order is important depending on the JS target. For example, `@Field.d(2, AwesomeArrayMessage)` requires that `AwesomeArrayMessage` has been defined earlier when targeting `ES5`.
|
|
525
|
-
|
|
526
|
-
```ts
|
|
527
|
-
import { Message, Type, Field, OneOf } from "protobufjs/light"; // respectively "./node_modules/protobufjs/light.js"
|
|
528
|
-
|
|
529
|
-
export class AwesomeSubMessage extends Message<AwesomeSubMessage> {
|
|
530
|
-
|
|
531
|
-
@Field.d(1, "string")
|
|
532
|
-
public awesomeString: string;
|
|
253
|
+
Alternatively, a custom constructor can be registered:
|
|
533
254
|
|
|
255
|
+
```js
|
|
256
|
+
function AwesomeMessage(properties) {
|
|
257
|
+
// ...
|
|
534
258
|
}
|
|
535
259
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
TWO = 2
|
|
539
|
-
}
|
|
260
|
+
root.lookupType("awesomepackage.AwesomeMessage").ctor = AwesomeMessage;
|
|
261
|
+
```
|
|
540
262
|
|
|
541
|
-
|
|
542
|
-
export class AwesomeMessage extends Message<AwesomeMessage> {
|
|
263
|
+
Custom constructors are populated with static `create`, `encode`, `encodeDelimited`, `decode`, `decodeDelimited`, `verify`, `fromObject`, `toObject`, and the instance method `toJSON`. The reflected type is available as `AwesomeMessage.$type` and `message.$type`.
|
|
543
264
|
|
|
544
|
-
|
|
545
|
-
public awesomeField: string;
|
|
265
|
+
### Services
|
|
546
266
|
|
|
547
|
-
|
|
548
|
-
public awesomeSubMessage: AwesomeSubMessage;
|
|
267
|
+
protobuf.js supports service clients built from reflected service definitions. The service API is transport-agnostic: provide an `rpcImpl` function to connect it to HTTP, WebSocket, gRPC, or another transport. See [examples/streaming-rpc.js](./examples/streaming-rpc.js) for details.
|
|
549
268
|
|
|
550
|
-
|
|
551
|
-
public awesomeEnum: AwesomeEnum;
|
|
269
|
+
### Descriptors
|
|
552
270
|
|
|
553
|
-
|
|
554
|
-
public which: string;
|
|
271
|
+
For `google/protobuf/descriptor.proto` interoperability, see [ext/descriptor](./ext/README.md#descriptor). Note that because protobuf.js does not use `descriptor.proto` internally, options are parsed and presented literally.
|
|
555
272
|
|
|
556
|
-
|
|
273
|
+
### Text format
|
|
557
274
|
|
|
558
|
-
|
|
559
|
-
let message = new AwesomeMessage({ awesomeField: "hello" });
|
|
560
|
-
let buffer = AwesomeMessage.encode(message).finish();
|
|
561
|
-
let decoded = AwesomeMessage.decode(buffer);
|
|
562
|
-
```
|
|
275
|
+
Protocol Buffers [Text Format](https://protobuf.dev/reference/protobuf/textformat-spec/) is supported via [ext/textformat](./ext/README.md#textformat).
|
|
563
276
|
|
|
564
|
-
|
|
277
|
+
### Content Security Policy
|
|
565
278
|
|
|
566
|
-
|
|
567
|
-
annotates a class as a protobuf message type. If `typeName` is not specified, the constructor's runtime function name is used for the reflected type.
|
|
279
|
+
In [CSP](https://w3c.github.io/webappsec-csp/)-restricted environments that disallow unsafe-eval, use generated static code instead of runtime code generation.
|
|
568
280
|
|
|
569
|
-
|
|
570
|
-
annotates a property as a protobuf field with the specified id and protobuf type.
|
|
281
|
+
## Conformance
|
|
571
282
|
|
|
572
|
-
|
|
573
|
-
annotates a property as a protobuf map field with the specified id, protobuf key and value type.
|
|
283
|
+
protobuf.js targets full binary wire-format conformance for **Proto2**, **Proto3** and **Editions**. CI runs the official Protocol Buffers conformance suite, with logs uploaded as artifacts.
|
|
574
284
|
|
|
575
|
-
|
|
576
|
-
|
|
285
|
+
| Syntax | Total | Required | Recommended |
|
|
286
|
+
| -------- | ------------------: | ----------------: | ----------------: |
|
|
287
|
+
| Proto2 | 100.00% (694/694) | 100.00% (485/485) | 100.00% (209/209) |
|
|
288
|
+
| Proto3 | 100.00% (689/689) | 100.00% (482/482) | 100.00% (207/207) |
|
|
289
|
+
| Editions | 100.00% (1176/1176) | 100.00% (926/926) | 100.00% (250/250) |
|
|
577
290
|
|
|
578
|
-
|
|
291
|
+
## Performance
|
|
579
292
|
|
|
580
|
-
|
|
581
|
-
* Enums are copied to a reflected enum with a generic name on decorator evaluation because referenced enum objects have no runtime name the decorator could use.
|
|
582
|
-
* Default values must be specified as arguments to the decorator instead of using a property initializer for proper prototype behavior.
|
|
583
|
-
* Property names on decorated classes must not be renamed on compile time (i.e. by a minifier) because decorators just receive the original field name as a string.
|
|
293
|
+
In both reflection and static modes, protobuf.js builds specialized encoders and decoders instead of interpreting descriptors at runtime.
|
|
584
294
|
|
|
585
|
-
|
|
295
|
+
The repository includes a [small benchmark](./bench). It compares protobuf.js reflection and static code against JSON encode/decode, protoc-gen-js, and protoc-gen-es. Results depend on hardware, Node.js version, and message shape, so they should be treated as indicative rather than absolute.
|
|
586
296
|
|
|
587
|
-
|
|
588
|
-
------------------------
|
|
297
|
+
One run on an AMD Ryzen 9 9950X3D with Node.js 24.15.0 produced:
|
|
589
298
|
|
|
590
|
-
|
|
591
|
-
|
|
299
|
+
```
|
|
300
|
+
benchmarking encode performance ...
|
|
592
301
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
302
|
+
protobuf.js reflect x 2,430,103 ops/sec ±0.62% (95 runs sampled)
|
|
303
|
+
protobuf.js static x 2,390,407 ops/sec ±0.42% (96 runs sampled)
|
|
304
|
+
JSON encode x 2,155,918 ops/sec ±0.63% (92 runs sampled)
|
|
305
|
+
protoc-gen-js x 995,429 ops/sec ±0.18% (98 runs sampled)
|
|
306
|
+
protoc-gen-es x 403,334 ops/sec ±0.14% (96 runs sampled)
|
|
597
307
|
|
|
598
|
-
|
|
599
|
-
|
|
308
|
+
protobuf.js reflect was fastest
|
|
309
|
+
protobuf.js static was 1.4% ops/sec slower (factor 1.0)
|
|
310
|
+
JSON encode was 11.3% ops/sec slower (factor 1.1)
|
|
311
|
+
protoc-gen-js was 58.9% ops/sec slower (factor 2.4)
|
|
312
|
+
protoc-gen-es was 83.3% ops/sec slower (factor 6.0)
|
|
600
313
|
|
|
601
|
-
|
|
602
|
-
-----------
|
|
603
|
-
The package includes a benchmark that compares protobuf.js performance to native JSON (as far as this is possible) and [Google's JS implementation](https://github.com/google/protobuf/tree/master/js). On an i7-2600K running node 6.9.1 it yields:
|
|
314
|
+
benchmarking decode performance ...
|
|
604
315
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
JSON (string) x 318,076 ops/sec ±0.63% (93 runs sampled)
|
|
611
|
-
JSON (buffer) x 179,165 ops/sec ±2.26% (91 runs sampled)
|
|
612
|
-
google-protobuf x 74,406 ops/sec ±0.85% (86 runs sampled)
|
|
613
|
-
|
|
614
|
-
protobuf.js (static) was fastest
|
|
615
|
-
protobuf.js (reflect) was 0.9% ops/sec slower (factor 1.0)
|
|
616
|
-
JSON (string) was 41.5% ops/sec slower (factor 1.7)
|
|
617
|
-
JSON (buffer) was 67.6% ops/sec slower (factor 3.1)
|
|
618
|
-
google-protobuf was 86.4% ops/sec slower (factor 7.3)
|
|
619
|
-
|
|
620
|
-
benchmarking decoding performance ...
|
|
621
|
-
|
|
622
|
-
protobuf.js (reflect) x 1,383,981 ops/sec ±0.88% (93 runs sampled)
|
|
623
|
-
protobuf.js (static) x 1,378,925 ops/sec ±0.81% (93 runs sampled)
|
|
624
|
-
JSON (string) x 302,444 ops/sec ±0.81% (93 runs sampled)
|
|
625
|
-
JSON (buffer) x 264,882 ops/sec ±0.81% (93 runs sampled)
|
|
626
|
-
google-protobuf x 179,180 ops/sec ±0.64% (94 runs sampled)
|
|
627
|
-
|
|
628
|
-
protobuf.js (reflect) was fastest
|
|
629
|
-
protobuf.js (static) was 0.3% ops/sec slower (factor 1.0)
|
|
630
|
-
JSON (string) was 78.1% ops/sec slower (factor 4.6)
|
|
631
|
-
JSON (buffer) was 80.8% ops/sec slower (factor 5.2)
|
|
632
|
-
google-protobuf was 87.0% ops/sec slower (factor 7.7)
|
|
633
|
-
|
|
634
|
-
benchmarking combined performance ...
|
|
635
|
-
|
|
636
|
-
protobuf.js (reflect) x 275,900 ops/sec ±0.78% (90 runs sampled)
|
|
637
|
-
protobuf.js (static) x 290,096 ops/sec ±0.96% (90 runs sampled)
|
|
638
|
-
JSON (string) x 129,381 ops/sec ±0.77% (90 runs sampled)
|
|
639
|
-
JSON (buffer) x 91,051 ops/sec ±0.94% (90 runs sampled)
|
|
640
|
-
google-protobuf x 42,050 ops/sec ±0.85% (91 runs sampled)
|
|
641
|
-
|
|
642
|
-
protobuf.js (static) was fastest
|
|
643
|
-
protobuf.js (reflect) was 4.7% ops/sec slower (factor 1.0)
|
|
644
|
-
JSON (string) was 55.3% ops/sec slower (factor 2.2)
|
|
645
|
-
JSON (buffer) was 68.6% ops/sec slower (factor 3.2)
|
|
646
|
-
google-protobuf was 85.5% ops/sec slower (factor 6.9)
|
|
647
|
-
```
|
|
316
|
+
protobuf.js reflect x 6,440,387 ops/sec ±0.25% (97 runs sampled)
|
|
317
|
+
protobuf.js static x 6,463,283 ops/sec ±0.27% (101 runs sampled)
|
|
318
|
+
JSON decode x 1,409,923 ops/sec ±0.11% (97 runs sampled)
|
|
319
|
+
protoc-gen-js x 947,647 ops/sec ±0.15% (99 runs sampled)
|
|
320
|
+
protoc-gen-es x 731,819 ops/sec ±0.28% (98 runs sampled)
|
|
648
321
|
|
|
649
|
-
|
|
322
|
+
protobuf.js static was fastest
|
|
323
|
+
protobuf.js reflect was 0.3% ops/sec slower (factor 1.0)
|
|
324
|
+
JSON decode was 78.2% ops/sec slower (factor 4.6)
|
|
325
|
+
protoc-gen-js was 85.3% ops/sec slower (factor 6.8)
|
|
326
|
+
protoc-gen-es was 88.7% ops/sec slower (factor 8.8)
|
|
650
327
|
|
|
651
|
-
|
|
652
|
-
* configuring the reader/writer interface according to the environment
|
|
653
|
-
* using node-specific functionality where beneficial and, of course
|
|
654
|
-
* avoiding unnecessary operations through splitting up [the toolset](#toolset).
|
|
328
|
+
benchmarking round-trip performance ...
|
|
655
329
|
|
|
656
|
-
|
|
330
|
+
protobuf.js reflect x 1,310,677 ops/sec ±0.21% (97 runs sampled)
|
|
331
|
+
protobuf.js static x 1,310,926 ops/sec ±0.26% (101 runs sampled)
|
|
332
|
+
JSON encode/decode x 741,714 ops/sec ±0.24% (99 runs sampled)
|
|
333
|
+
protoc-gen-js x 472,844 ops/sec ±0.09% (96 runs sampled)
|
|
334
|
+
protoc-gen-es x 254,044 ops/sec ±0.05% (101 runs sampled)
|
|
657
335
|
|
|
658
|
-
|
|
659
|
-
|
|
336
|
+
protobuf.js reflect was fastest
|
|
337
|
+
protobuf.js static was 0.0% ops/sec slower (factor 1.0)
|
|
338
|
+
JSON encode/decode was 43.4% ops/sec slower (factor 1.8)
|
|
339
|
+
protoc-gen-js was 63.9% ops/sec slower (factor 2.8)
|
|
340
|
+
protoc-gen-es was 80.6% ops/sec slower (factor 5.2)
|
|
660
341
|
```
|
|
661
342
|
|
|
662
|
-
|
|
343
|
+
Run it locally with:
|
|
663
344
|
|
|
664
|
-
```
|
|
665
|
-
|
|
345
|
+
```sh
|
|
346
|
+
npm --prefix bench install
|
|
347
|
+
npm run bench
|
|
666
348
|
```
|
|
667
349
|
|
|
668
|
-
|
|
350
|
+
## Compatibility
|
|
669
351
|
|
|
670
|
-
|
|
671
|
-
-------------
|
|
352
|
+
Supported runtimes are browsers, Node.js v12+, Deno and Bun. When using the CLI with Bun, Node.js must also be installed.
|
|
672
353
|
|
|
673
|
-
|
|
674
|
-
* Because the internals of this package do not rely on `google/protobuf/descriptor.proto`, options are parsed and presented literally.
|
|
675
|
-
* If typed arrays are not supported by the environment, plain arrays will be used instead.
|
|
676
|
-
* Support for pre-ES5 environments (except IE8) can be achieved by [using a polyfill](https://github.com/protobufjs/protobuf.js/blob/master/lib/polyfill.js).
|
|
677
|
-
* Support for [Content Security Policy](https://w3c.github.io/webappsec-csp/)-restricted environments (like Chrome extensions without unsafe-eval) can be achieved by generating and using static code instead.
|
|
678
|
-
* If a proper way to work with 64 bit values (uint64, int64 etc.) is required, just install [long.js](https://github.com/dcodeIO/long.js) alongside this library. All 64 bit numbers will then be returned as a `Long` instance instead of a possibly unsafe JavaScript number ([see](https://github.com/dcodeIO/long.js)).
|
|
679
|
-
* For descriptor.proto interoperability, see [ext/descriptor](https://github.com/protobufjs/protobuf.js/tree/master/ext/descriptor)
|
|
354
|
+
## Security
|
|
680
355
|
|
|
681
|
-
|
|
682
|
-
--------
|
|
356
|
+
protobuf.js favors transparent disclosure. Security-impacting reports are handled through coordinated GitHub Security Advisories where appropriate. See [SECURITY.md](./SECURITY.md) for supported release lines, reporting instructions, and notes on untrusted schema input.
|
|
683
357
|
|
|
684
|
-
|
|
358
|
+
## Development
|
|
685
359
|
|
|
686
|
-
```
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
Building the respective development and production versions with their respective source maps to `dist/`:
|
|
693
|
-
|
|
694
|
-
```
|
|
695
|
-
$> npm run build
|
|
360
|
+
```sh
|
|
361
|
+
git clone https://github.com/protobufjs/protobuf.js
|
|
362
|
+
cd protobuf.js
|
|
363
|
+
npm install
|
|
696
364
|
```
|
|
697
365
|
|
|
698
|
-
|
|
366
|
+
Running the tests:
|
|
699
367
|
|
|
700
|
-
```
|
|
701
|
-
|
|
368
|
+
```sh
|
|
369
|
+
npm test
|
|
702
370
|
```
|
|
703
371
|
|
|
704
|
-
Building the
|
|
372
|
+
Building the development and production versions with their respective source maps to `dist/`:
|
|
705
373
|
|
|
374
|
+
```sh
|
|
375
|
+
npm run build
|
|
706
376
|
```
|
|
707
|
-
$> npm run build:types
|
|
708
|
-
```
|
|
709
|
-
|
|
710
|
-
### Browserify integration
|
|
711
|
-
|
|
712
|
-
By default, protobuf.js integrates into any browserify build-process without requiring any optional modules. Hence:
|
|
713
|
-
|
|
714
|
-
* If int64 support is required, explicitly require the `long` module somewhere in your project as it will be excluded otherwise. This assumes that a global `require` function is present that protobuf.js can call to obtain the long module.
|
|
715
377
|
|
|
716
|
-
|
|
378
|
+
## Additional documentation
|
|
717
379
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
protobuf.util.Long = Long;
|
|
722
|
-
protobuf.configure();
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
* If you have any special requirements, there is [the bundler](https://github.com/protobufjs/protobuf.js/blob/master/scripts/bundle.js) for reference.
|
|
726
|
-
|
|
727
|
-
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
|
|
380
|
+
* [API Documentation](https://protobufjs.github.io/protobuf.js)
|
|
381
|
+
* [Changelog](./CHANGELOG.md)
|
|
382
|
+
* [Protocol Buffers Documentation](https://protobuf.dev/)
|