@trevrpc/trevrpc-js 1.1.0 → 1.2.0

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 CHANGED
@@ -101,7 +101,7 @@ call.
101
101
 
102
102
  - Failed calls throw `TrevRpcError` with a `code` (`Code.NotFound`, ...), `statusMessage` and `metadata`. A deadline surfaces as `Code.DeadlineExceeded`, a cancelled call as `Code.Cancelled` (with the abort reason as `cause`), and a lost connection as `Code.Unavailable`.
103
103
  - Streaming responses end with the server's final status: iteration finishes after `OK` and throws the `TrevRpcError` otherwise. `stream.status` settles with the same outcome and carries trailing metadata. Leaving a `for await` loop early, or calling `close()`, cancels the call.
104
- - Response headers and trailing metadata are separate. Every call reports them to the `onResponseHeaders(headers)` and `onResponseMetadata(metadata)` callbacks of its options: the headers (empty when the server sent none) as soon as the first response frame arrives, and the trailing metadata of the final status when the call succeeds, before its result is returned or its stream ends. A failed call carries its metadata on the `TrevRpcError`, and a callback that throws fails the call. Server-streaming and bidirectional calls also have a `headers` promise that resolves as soon as the first response frame arrives, so headers are available before the first message, and rejects with the call's error if the call fails first.
104
+ - Response headers and trailing metadata are separate. Every call reports them to the `onResponseHeaders(headers)` and `onResponseMetadata(metadata)` callbacks of its options: the headers (empty when the server sent none) as soon as they, the first message or the final status arrive, and the trailing metadata of the final status when the call succeeds, before its result is returned or its stream ends. A failed call carries its metadata on the `TrevRpcError`, and a callback that throws fails the call. Server-streaming and bidirectional calls also have a `headers` promise that resolves as soon as the headers, the first message or the final status arrive, so headers are available before the first message, and rejects with the call's error if the call fails first.
105
105
  - Frames follow the [wire format](https://trev.zip/llc/TrevRPC/wiki/Protocol-and-Wire-Format): a type, a length and a payload, with messages sent as raw protobuf. The client skips frame types it does not know, and `maxFrameSize` limits every frame, unknown ones included.
106
106
  - The server's response decides the outcome of a call, and a call reports it as soon as the final status arrives. If the server ends a call before the upload is done (client-streaming and bidirectional calls), the upload is cancelled and `send()` rejects at once, without waiting for the server to stop reading and whether or not the caller receives:
107
107
  - with the server's `TrevRpcError` if its status is not OK, and the same error is the call's outcome (`closeAndRecv()`, `recv()`, `status`);
@@ -132,6 +132,35 @@ const channel = await connect(url, {
132
132
 
133
133
  Any object with `createBidirectionalStream()`, including a plain `WebTransport` session, can be used as the transport of a generated client. Create such a session with `new WebTransport(url, { protocols: ["trevrpc-1"] })` so the server knows the wire version. Requests name the method by its full path, `/<package.Service>/<Method>` (for example `/example.greeter.Greeter/SayHello`), which the generated clients build from the service and method names.
134
134
 
135
+ ### Connection metadata
136
+
137
+ Metadata every call of a channel carries, such as a bearer token, can be set once on the channel instead of on each call. The channel sends it in full on the first calls of each session, until the server confirms that it stored it for the session, and refers to it by ID after that, so it crosses the connection once. The server merges it into each call's metadata, and a call's own `metadata` wins over an entry with the same key.
138
+
139
+ ```js
140
+ const channel = await connect(url, { connectionMetadata: { authorization: `Bearer ${token}` } });
141
+ channel.setConnectionMetadata({ authorization: `Bearer ${refreshed}` }); // calls started from now on
142
+ channel.setConnectionMetadata(); // removes it
143
+ ```
144
+
145
+ A changed set is sent in full again on every session, and so is the set on a session after a reconnect. Keys follow the rules of call metadata. The `Channel` is the only transport that supports it.
146
+
147
+ ### Compression
148
+
149
+ Messages can travel compressed with zstd and a dictionary trained on them (see [Compression](https://trev.zip/llc/TrevRPC/wiki/Compression)). The codec lives in a separate entry point, `@trevrpc/trevrpc-js/zstd`, which loads libzstd as WebAssembly (about 85 KB gzipped), so applications without compression never load it:
150
+
151
+ ```js
152
+ import { createCompression } from "@trevrpc/trevrpc-js/zstd";
153
+
154
+ const compression = await createCompression({
155
+ dictionaries: [{ data: dictionaryBytes, messages: ["example.greeter.HelloRequest"] }],
156
+ });
157
+ const channel = await connect(url, { compression });
158
+ ```
159
+
160
+ Generated clients pick each message's dictionary by its protobuf type. The channel asks each new session's server which dictionaries it holds, so a message whose dictionary the server lacks travels uncompressed, and request messages are compressed once the answer arrives. A transport other than a `Channel` compresses when it has a `compression` property with these settings.
161
+
162
+ Compression settings also enable stream compression, even without dictionaries (`createCompression()`): streaming methods marked `option (trevrpc.method) = {compression: COMPRESSION_STREAM}` compress each streamed direction with one zstd context per call, from its third message, so later messages compress against earlier ones. The contexts of a channel's calls may hold up to `streamCompressionMemory` bytes (64 MiB by default; 0 turns stream compression off).
163
+
135
164
  ### WebSocket fallback
136
165
 
137
166
  `connect()` races two transports. WebTransport starts first; QMux over WebSocket (subprotocol `qmux-02.trevrpc-1`, served by Go and Rust on the server's TCP port) starts after `fallbackDelayMs` (default 300) or immediately if WebTransport fails or the browser has no `WebTransport` API. The first session to be ready wins and the other is closed. After the WebSocket wins, reconnects use it directly until `reprobeIntervalMs` (default 5 minutes) has passed since WebTransport was lost, then race again.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trevrpc/trevrpc-js",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Browser WebTransport client and protobuf.js code generator for TrevRPC",
5
5
  "homepage": "https://trev.zip/llc/TrevRPC",
6
6
  "bugs": {
@@ -26,13 +26,17 @@
26
26
  ".": {
27
27
  "types": "./src/index.d.ts",
28
28
  "import": "./src/index.js"
29
+ },
30
+ "./zstd": {
31
+ "types": "./src/zstd.d.ts",
32
+ "import": "./src/zstd.js"
29
33
  }
30
34
  },
31
35
  "publishConfig": {
32
36
  "access": "public"
33
37
  },
34
38
  "scripts": {
35
- "build": "node interop-browser/build.js",
39
+ "build": "node zstd-wasm/embed.js && node interop-browser/build.js",
36
40
  "format": "oxfmt --write",
37
41
  "format:check": "oxfmt --check",
38
42
  "lint": "oxlint --deny-warnings",
@@ -45,12 +49,16 @@
45
49
  "protobufjs": "^8.8.1"
46
50
  },
47
51
  "devDependencies": {
52
+ "@bufbuild/protobuf": "^2.16.0",
53
+ "@bufbuild/protoc-gen-es": "^2.16.0",
54
+ "@connectrpc/connect": "^2.3.0",
55
+ "@connectrpc/connect-web": "^2.3.0",
48
56
  "playwright": "1.64.1",
49
- "rolldown": "^1.2.14",
57
+ "rolldown": "^1.2.16",
50
58
  "typescript": "^7.0.2"
51
59
  },
52
60
  "engines": {
53
61
  "node": ">=24"
54
62
  },
55
- "packageManager": "npm@12.2.0"
63
+ "packageManager": "npm@12.2.1"
56
64
  }