@statewalker/webrun-rpc 0.7.0 → 0.10.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 +189 -12
- package/dist/connect-serve.d.ts +2 -0
- package/dist/connect-serve.d.ts.map +1 -1
- package/dist/duplex-over-port.d.ts +3 -1
- package/dist/duplex-over-port.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +496 -101
- package/dist/multiplex-port.d.ts +2 -0
- package/dist/multiplex-port.d.ts.map +1 -1
- package/dist/port-credit.d.ts +51 -0
- package/dist/port-credit.d.ts.map +1 -1
- package/dist/port-types.d.ts +37 -2
- package/dist/port-types.d.ts.map +1 -1
- package/dist/structured-codec.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/connect-serve.ts +20 -9
- package/src/duplex-over-port.ts +345 -40
- package/src/index.ts +6 -1
- package/src/multiplex-port.ts +238 -21
- package/src/port-credit.ts +86 -0
- package/src/port-types.ts +32 -3
- package/src/structured-codec.ts +5 -1
package/dist/multiplex-port.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ import type { PortInfo, PortMux, PortMuxOptions } from "./port-types.js";
|
|
|
7
7
|
export declare const MUX_CLOSED_MESSAGE = "webrun-rpc: the multiplexer was closed";
|
|
8
8
|
/** Ceiling on concurrently open virtual ports. Bounds the id table only. */
|
|
9
9
|
export declare const DEFAULT_MAX_PORTS = 1024;
|
|
10
|
+
/** Default ceiling on one message reassembled from frames (`maxReassembledBytes`). */
|
|
11
|
+
export declare const DEFAULT_MAX_REASSEMBLED_BYTES: number;
|
|
10
12
|
/**
|
|
11
13
|
* What a message costs a port's window when the codec cannot say
|
|
12
14
|
* (`PortCodec.encode`): its bytes and string lengths, found in its values up
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multiplex-port.d.ts","sourceRoot":"","sources":["../src/multiplex-port.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"multiplex-port.d.ts","sourceRoot":"","sources":["../src/multiplex-port.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQzD,OAAO,KAAK,EAIV,QAAQ,EACR,OAAO,EACP,cAAc,EACf,MAAM,iBAAiB,CAAC;AAGzB;;;GAGG;AACH,eAAO,MAAM,kBAAkB,2CAA2C,CAAC;AA6B3E,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,sFAAsF;AACtF,eAAO,MAAM,6BAA6B,QAAmB,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAc5D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,GAAG;IAAE,KAAK,IAAI,QAAQ,EAAE,CAAA;CAAE,CAmzBnC"}
|
package/dist/port-credit.d.ts
CHANGED
|
@@ -24,4 +24,55 @@ export declare function portBufferedAmount(port: MessageTarget): number;
|
|
|
24
24
|
* task (for a port without flow control, on the next one).
|
|
25
25
|
*/
|
|
26
26
|
export declare function whenPortReady(port: MessageTarget, below?: number): Promise<void>;
|
|
27
|
+
/** A capability two ends agree on for one windowed port, in its `open` and the ack. */
|
|
28
|
+
export type PortCap = "pipeline" | "end";
|
|
29
|
+
/**
|
|
30
|
+
* What two ends have agreed for one windowed port so far. `caps`: what both
|
|
31
|
+
* speak, and so what the peer may send; empty until the handshake settles it
|
|
32
|
+
* (the opener learns it from the ack, the responder from the `open`).
|
|
33
|
+
* `enforced`: the window holds this end's own sends — what this end needs
|
|
34
|
+
* before it relies on the window instead of a confirmation per message.
|
|
35
|
+
*/
|
|
36
|
+
export interface PortAgreement {
|
|
37
|
+
window: number;
|
|
38
|
+
caps: ReadonlySet<PortCap>;
|
|
39
|
+
enforced: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** @internal Registered by the multiplexer for each port with a window. */
|
|
42
|
+
export declare function setPortAgreement(port: MessageTarget, agreement: () => PortAgreement | undefined): void;
|
|
43
|
+
/**
|
|
44
|
+
* @internal What has been agreed with the peer on `port` so far; `undefined`
|
|
45
|
+
* on a port without a window. Not exported from the package.
|
|
46
|
+
*/
|
|
47
|
+
export declare function portAgreement(port: MessageTarget): PortAgreement | undefined;
|
|
48
|
+
/** @internal The half-close of one windowed port (capability `"end"`). */
|
|
49
|
+
export interface PortEndState {
|
|
50
|
+
/** Queue this side's `end`; `false` when `end` was not agreed. */
|
|
51
|
+
end(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Calls `resolve` once the peer has ended its direction (at once if it has
|
|
54
|
+
* already); `false`, and `resolve` is never called, when `end` was not
|
|
55
|
+
* agreed. The mux holds `resolve` weakly, so a port dropped while someone
|
|
56
|
+
* waits on it can still be collected (`onLeak`).
|
|
57
|
+
*/
|
|
58
|
+
watchPeerEnd(resolve: () => void): boolean;
|
|
59
|
+
}
|
|
60
|
+
/** @internal Registered by the multiplexer for each port with a window. */
|
|
61
|
+
export declare function setPortEndState(port: MessageTarget, state: PortEndState): void;
|
|
62
|
+
/**
|
|
63
|
+
* @internal End this side's direction of `port`: an `end` is queued behind
|
|
64
|
+
* everything already posted on it, and anything posted afterwards is dropped.
|
|
65
|
+
* `false`, and nothing changes, when `end` was not agreed (no window, the
|
|
66
|
+
* handshake not answered yet, or a peer that does not speak it): the caller
|
|
67
|
+
* then closes the port. Never waits on the peer. Not exported from the package.
|
|
68
|
+
*/
|
|
69
|
+
export declare function endPort(port: MessageTarget): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* @internal Resolves once the peer has ended its direction of `port`. It never
|
|
72
|
+
* settles otherwise: not on a port where `end` is not agreed when it is asked
|
|
73
|
+
* (no window, the handshake not answered yet, a peer or codec without it), and
|
|
74
|
+
* not when the port closes first, so a caller races it against the port's
|
|
75
|
+
* close signal. Not exported from the package.
|
|
76
|
+
*/
|
|
77
|
+
export declare function whenPortEnded(port: MessageTarget): Promise<void>;
|
|
27
78
|
//# sourceMappingURL=port-credit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port-credit.d.ts","sourceRoot":"","sources":["../src/port-credit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,cAAc,IAAI,MAAM,CAAC;IACzB,kEAAkE;IAClE,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AASD,gBAAgB;AAChB,eAAO,MAAM,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAenC,CAAC;AAIT,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3E"}
|
|
1
|
+
{"version":3,"file":"port-credit.d.ts","sourceRoot":"","sources":["../src/port-credit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,cAAc,IAAI,MAAM,CAAC;IACzB,kEAAkE;IAClE,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AASD,gBAAgB;AAChB,eAAO,MAAM,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAenC,CAAC;AAIT,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAEhF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3E;AAED,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAID,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,GAAG,SAAS,QAE/F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS,CAE5E;AAED,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,GAAG,IAAI,OAAO,CAAC;IACf;;;;;OAKG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC5C;AAID,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAahE"}
|
package/dist/port-types.d.ts
CHANGED
|
@@ -7,12 +7,15 @@ import type { MessageTarget } from "./message-target.js";
|
|
|
7
7
|
* and no error type: `close` carries an opaque `reason` that layer 1 never
|
|
8
8
|
* inspects, because stream semantics belong above this layer.
|
|
9
9
|
*/
|
|
10
|
-
export type PortEnvelope =
|
|
10
|
+
export type PortEnvelope =
|
|
11
|
+
/** `caps` (with a window): the capabilities the opener speaks on this port. */
|
|
12
|
+
{
|
|
11
13
|
type: "open";
|
|
12
14
|
id: number;
|
|
13
15
|
meta?: unknown;
|
|
14
16
|
window?: number;
|
|
15
17
|
exact?: boolean;
|
|
18
|
+
caps?: string[];
|
|
16
19
|
} | {
|
|
17
20
|
type: "message";
|
|
18
21
|
id: number;
|
|
@@ -22,12 +25,22 @@ export type PortEnvelope = {
|
|
|
22
25
|
id: number;
|
|
23
26
|
reason?: unknown;
|
|
24
27
|
}
|
|
25
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Per-port flow control (`window`): the receiver has consumed `bytes` more.
|
|
30
|
+
* The responder's zero-byte ack carries `caps`, the shared subset, when the
|
|
31
|
+
* opener listed some.
|
|
32
|
+
*/
|
|
26
33
|
| {
|
|
27
34
|
type: "credit";
|
|
28
35
|
id: number;
|
|
29
36
|
bytes: number;
|
|
30
37
|
exact?: boolean;
|
|
38
|
+
caps?: string[];
|
|
39
|
+
}
|
|
40
|
+
/** Half-close (capability `"end"`): the sender's direction of the port has ended. */
|
|
41
|
+
| {
|
|
42
|
+
type: "end";
|
|
43
|
+
id: number;
|
|
31
44
|
}
|
|
32
45
|
/** Fair framing (`frameSize`): one piece of an encoded `message` envelope. */
|
|
33
46
|
| {
|
|
@@ -66,6 +79,15 @@ export interface PortCodec {
|
|
|
66
79
|
encode?(envelope: PortEnvelope): Uint8Array;
|
|
67
80
|
/** Optional, with `encode`: an envelope back from its bytes, or `undefined`. */
|
|
68
81
|
decode?(data: unknown): PortEnvelope | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Optional: this codec's `read` (and `decode`) accept the `end` envelope.
|
|
84
|
+
* Only then does a windowed port offer the `end` capability. A codec that
|
|
85
|
+
* dropped `end` would leave a port that ended normally in the peer's table
|
|
86
|
+
* (`ports()`) until the mux closes, with no error anywhere. A codec spread
|
|
87
|
+
* from a built-in (`{ ...structuredCodec, read }`) inherits the flag: its
|
|
88
|
+
* own `read` must then accept `end` too, or it must drop the flag.
|
|
89
|
+
*/
|
|
90
|
+
halfClose?: true;
|
|
69
91
|
}
|
|
70
92
|
export interface PortMuxOptions {
|
|
71
93
|
/** How envelopes are placed on the underlying port. */
|
|
@@ -147,6 +169,19 @@ export interface PortMuxOptions {
|
|
|
147
169
|
* whole. 16-64 KiB is a reasonable range.
|
|
148
170
|
*/
|
|
149
171
|
frameSize?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Ceiling, in bytes, on what this side holds of a peer's framed messages
|
|
174
|
+
* past their ports' windows, summed over all ports (default 64 MiB).
|
|
175
|
+
* A partial message counts against its port's window as it arrives: one
|
|
176
|
+
* begun while this side still owed credit must fit what the window left,
|
|
177
|
+
* and one begun with nothing owed may pass the window, its excess charged
|
|
178
|
+
* to this cap. A frame past either limit makes the mux drop that port's
|
|
179
|
+
* partial message, close the port with a `RangeError` and send the peer a
|
|
180
|
+
* close with reason `"max-reassembled-bytes"`. A framed message more than
|
|
181
|
+
* this cap past the window never arrives, though the same message sent
|
|
182
|
+
* whole would.
|
|
183
|
+
*/
|
|
184
|
+
maxReassembledBytes?: number;
|
|
150
185
|
/**
|
|
151
186
|
* Liveness of the peer (off when unset). Every `intervalMs` the mux pings
|
|
152
187
|
* and the peer answers; anything from it counts as an answer. After `misses`
|
package/dist/port-types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port-types.d.ts","sourceRoot":"","sources":["../src/port-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"port-types.d.ts","sourceRoot":"","sources":["../src/port-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-codec.d.ts","sourceRoot":"","sources":["../src/structured-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"structured-codec.d.ts","sourceRoot":"","sources":["../src/structured-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAgB,MAAM,iBAAiB,CAAC;AAmB/D;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,SAa7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statewalker/webrun-rpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Ports and RPC over them: a port multiplexer, and typed request/response and streaming primitives over any MessageTarget.",
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
"rolldown": "^1.2.12",
|
|
40
40
|
"typescript": "^7.0.2",
|
|
41
41
|
"vitest": "^5.0.3",
|
|
42
|
+
"webrun-rpc-0-5": "npm:@statewalker/webrun-rpc@0.5.1",
|
|
43
|
+
"webrun-rpc-0-7": "npm:@statewalker/webrun-rpc@0.7.0",
|
|
44
|
+
"webrun-rpc-0-8": "npm:@statewalker/webrun-rpc@0.8.0",
|
|
42
45
|
"@statewalker/webrun-streams-conformance": "^0.3.3"
|
|
43
46
|
},
|
|
44
47
|
"sideEffects": false,
|
|
@@ -49,6 +52,7 @@
|
|
|
49
52
|
"scripts": {
|
|
50
53
|
"build": "rimraf dist && rolldown -c && tsc --emitDeclarationOnly --declaration",
|
|
51
54
|
"test": "vitest run",
|
|
55
|
+
"bench": "vitest run --config vitest.bench.config.ts && echo \"all benchmarks passed\"",
|
|
52
56
|
"typecheck": "tsc --noEmit",
|
|
53
57
|
"typecheck:tests": "tsc -p tsconfig.tests.json",
|
|
54
58
|
"lint": "biome check src tests"
|
package/src/connect-serve.ts
CHANGED
|
@@ -139,15 +139,24 @@ export const serve: Serve<PortParams> = async ({ mux: factory, timeout }, handle
|
|
|
139
139
|
// reaches it as `return()` through `throughAbort`, so the `finally` runs
|
|
140
140
|
// on every ending — normal exhaustion, handler throw, peer abort, local
|
|
141
141
|
// teardown. `serveDuplexOverPort` reports no completion of its own.
|
|
142
|
-
const tracked: Duplex = (input) =>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
const tracked: Duplex = (input) => {
|
|
143
|
+
const output = handler(input);
|
|
144
|
+
// `return()` on this wrapper is queued behind its pending `next()`, as on
|
|
145
|
+
// any async generator, so the abandonment would reach the handler only
|
|
146
|
+
// once it answers. Forwarded at once, a handler still waiting (an HTTP
|
|
147
|
+
// long poll) learns now that its caller left.
|
|
148
|
+
return returningAtOnce(
|
|
149
|
+
(async function* () {
|
|
150
|
+
try {
|
|
151
|
+
yield* output;
|
|
152
|
+
} finally {
|
|
153
|
+
finished = true;
|
|
154
|
+
if (off) live.delete(off);
|
|
155
|
+
}
|
|
156
|
+
})(),
|
|
157
|
+
() => void output.return(undefined).catch(() => {}),
|
|
158
|
+
);
|
|
159
|
+
};
|
|
151
160
|
off = serveDuplexOverPort(port, tracked, streamOptions);
|
|
152
161
|
// `serveDuplexOverPort` invokes the handler synchronously. The generator
|
|
153
162
|
// body above is lazy, so today it cannot have finished by the time `off`
|
|
@@ -201,6 +210,8 @@ export interface OverPipeOptions {
|
|
|
201
210
|
window?: number;
|
|
202
211
|
/** Fair framing in bytes — see `PortMuxOptions.frameSize`. */
|
|
203
212
|
frameSize?: number;
|
|
213
|
+
/** Ceiling on a message reassembled from frames — see `PortMuxOptions.maxReassembledBytes`. */
|
|
214
|
+
maxReassembledBytes?: number;
|
|
204
215
|
/** Liveness of the peer by ping/pong — see `PortMuxOptions.keepalive`. */
|
|
205
216
|
keepalive?: { intervalMs: number; misses?: number };
|
|
206
217
|
/** Development aid: report ports dropped without `close()` — see `PortMuxOptions.onLeak`. */
|