@net-mesh/browser 0.37.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/CHANGELOG.md +517 -0
- package/LICENSE-APACHE +190 -0
- package/LICENSE-MIT +21 -0
- package/README.md +666 -0
- package/dist/async-queue.d.ts +26 -0
- package/dist/async-queue.js +62 -0
- package/dist/credential.d.ts +70 -0
- package/dist/credential.js +95 -0
- package/dist/errors.d.ts +400 -0
- package/dist/errors.js +726 -0
- package/dist/events.d.ts +232 -0
- package/dist/events.js +298 -0
- package/dist/identity.d.ts +40 -0
- package/dist/identity.js +78 -0
- package/dist/index.bundle.js +2 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +46 -0
- package/dist/leader/events.d.ts +111 -0
- package/dist/leader/events.js +116 -0
- package/dist/leader/index.d.ts +14 -0
- package/dist/leader/index.js +11 -0
- package/dist/leader/session.d.ts +539 -0
- package/dist/leader/session.js +770 -0
- package/dist/leader/wasm.d.ts +123 -0
- package/dist/leader/wasm.js +39 -0
- package/dist/lobby.d.ts +183 -0
- package/dist/lobby.js +504 -0
- package/dist/local.d.ts +80 -0
- package/dist/local.js +160 -0
- package/dist/net_leaf.d.ts +1494 -0
- package/dist/net_leaf.js +3753 -0
- package/dist/net_leaf_bg.wasm +0 -0
- package/dist/net_leaf_bg.wasm.d.ts +137 -0
- package/dist/netcode/client.d.ts +102 -0
- package/dist/netcode/client.js +296 -0
- package/dist/netcode/clock.d.ts +45 -0
- package/dist/netcode/clock.js +54 -0
- package/dist/netcode/host.d.ts +118 -0
- package/dist/netcode/host.js +276 -0
- package/dist/netcode/index.d.ts +19 -0
- package/dist/netcode/index.js +14 -0
- package/dist/netcode/interpolate.d.ts +50 -0
- package/dist/netcode/interpolate.js +100 -0
- package/dist/netcode/wire.d.ts +125 -0
- package/dist/netcode/wire.js +117 -0
- package/dist/node.d.ts +908 -0
- package/dist/node.js +1085 -0
- package/dist/org.d.ts +412 -0
- package/dist/org.js +567 -0
- package/dist/peer-driver.d.ts +117 -0
- package/dist/peer-driver.js +224 -0
- package/dist/store/assembly.d.ts +176 -0
- package/dist/store/assembly.js +325 -0
- package/dist/store/chunker.d.ts +83 -0
- package/dist/store/chunker.js +190 -0
- package/dist/store/core.d.ts +136 -0
- package/dist/store/core.js +477 -0
- package/dist/store/definition.d.ts +23 -0
- package/dist/store/definition.js +83 -0
- package/dist/store/errors.d.ts +77 -0
- package/dist/store/errors.js +94 -0
- package/dist/store/host.d.ts +247 -0
- package/dist/store/host.js +675 -0
- package/dist/store/index.d.ts +50 -0
- package/dist/store/index.js +40 -0
- package/dist/store/interest.d.ts +40 -0
- package/dist/store/interest.js +77 -0
- package/dist/store/inventory.d.ts +81 -0
- package/dist/store/inventory.js +140 -0
- package/dist/store/join.d.ts +118 -0
- package/dist/store/join.js +724 -0
- package/dist/store/json.d.ts +50 -0
- package/dist/store/json.js +283 -0
- package/dist/store/ledger.d.ts +187 -0
- package/dist/store/ledger.js +292 -0
- package/dist/store/owner.d.ts +616 -0
- package/dist/store/owner.js +1711 -0
- package/dist/store/patch.d.ts +70 -0
- package/dist/store/patch.js +166 -0
- package/dist/store/player.d.ts +65 -0
- package/dist/store/player.js +261 -0
- package/dist/store/replica.d.ts +187 -0
- package/dist/store/replica.js +740 -0
- package/dist/store/state.d.ts +42 -0
- package/dist/store/state.js +165 -0
- package/dist/store/types.d.ts +200 -0
- package/dist/store/types.js +25 -0
- package/dist/store/visibility.d.ts +118 -0
- package/dist/store/visibility.js +282 -0
- package/dist/store/wire.d.ts +309 -0
- package/dist/store/wire.js +834 -0
- package/dist/stream.d.ts +174 -0
- package/dist/stream.js +238 -0
- package/dist/three/index.d.ts +109 -0
- package/dist/three/index.js +130 -0
- package/dist/udp-probe.d.ts +159 -0
- package/dist/udp-probe.js +245 -0
- package/dist/wasm.d.ts +642 -0
- package/dist/wasm.js +98 -0
- package/dist/world/border.d.ts +84 -0
- package/dist/world/border.js +99 -0
- package/dist/world/handoff.d.ts +187 -0
- package/dist/world/handoff.js +222 -0
- package/dist/world/index.d.ts +13 -0
- package/dist/world/index.js +9 -0
- package/dist/world/link.d.ts +179 -0
- package/dist/world/link.js +476 -0
- package/dist/world/regions.d.ts +154 -0
- package/dist/world/regions.js +314 -0
- package/package.json +72 -0
package/dist/wasm.d.ts
ADDED
|
@@ -0,0 +1,642 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wasm-bindgen boundary, described in TypeScript.
|
|
3
|
+
*
|
|
4
|
+
* These are the *only* shapes this package assumes about
|
|
5
|
+
* `net-mesh-leaf`. They are snake_case because that is what
|
|
6
|
+
* `wasm-bindgen` emits from Rust method names; every camelCase name a
|
|
7
|
+
* consumer sees is added by {@link BrowserNode} one layer up. Keeping
|
|
8
|
+
* the boundary in one file means a change on the Rust side breaks
|
|
9
|
+
* compilation here, at the seam, instead of somewhere in the middle of
|
|
10
|
+
* the wrapper.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* `LeafNode.connect`'s argument, exactly as the Rust side reads it
|
|
14
|
+
* (`wasm.rs`: `credentialB64`, `bootstrapUrl?`, `origin`,
|
|
15
|
+
* `iceServers?`, `entitySecretHex?`, `noiseSecretHex?`).
|
|
16
|
+
*/
|
|
17
|
+
export interface LeafWasmConnectOptions {
|
|
18
|
+
/** The bootstrap credential, base64. */
|
|
19
|
+
credentialB64: string;
|
|
20
|
+
/**
|
|
21
|
+
* The anchor's HTTPS bootstrap endpoint. Optional: the credential
|
|
22
|
+
* carries one, and this overrides it when present.
|
|
23
|
+
*/
|
|
24
|
+
bootstrapUrl?: string;
|
|
25
|
+
/** The origin this node belongs to — the identity's trust boundary. */
|
|
26
|
+
origin: string;
|
|
27
|
+
/**
|
|
28
|
+
* Extra ICE servers, when the page wants them.
|
|
29
|
+
*
|
|
30
|
+
* Real `RTCIceServer` objects: `urls` a string or an array of
|
|
31
|
+
* them, plus `username`/`credential` for TURN. Rust parses this
|
|
32
|
+
* shape (`wasm.rs: parse_ice_servers`) and refuses anything else
|
|
33
|
+
* — a bare URL string included — rather than dropping it.
|
|
34
|
+
*/
|
|
35
|
+
iceServers?: readonly RTCIceServer[];
|
|
36
|
+
/** Custodial Ed25519 entity secret, 32 bytes of hex. */
|
|
37
|
+
entitySecretHex?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Custodial Noise X25519 static secret, 32 bytes of hex. The Rust
|
|
40
|
+
* side reads it only when `entitySecretHex` is also present.
|
|
41
|
+
*/
|
|
42
|
+
noiseSecretHex?: string;
|
|
43
|
+
}
|
|
44
|
+
/** How a stream behaves. Mirrors the leaf's two stream profiles. */
|
|
45
|
+
export type StreamReliability = 'reliable' | 'fireAndForget';
|
|
46
|
+
/** `open_stream`'s argument. */
|
|
47
|
+
export interface LeafWasmStreamOptions {
|
|
48
|
+
reliability: StreamReliability;
|
|
49
|
+
/** A human label for logs. */
|
|
50
|
+
label?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Used verbatim when present, so a stream can match a publish
|
|
53
|
+
* contract a native handler dispatches on. Decimal or `0x`-hex,
|
|
54
|
+
* and a **string** because a `u64` does not survive a JS number.
|
|
55
|
+
*/
|
|
56
|
+
streamId?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Likewise verbatim: the `u16` channel hash the stream rides.
|
|
59
|
+
*
|
|
60
|
+
* A **number**, which is what Rust reads. It was declared a
|
|
61
|
+
* string here while `wasm.rs` read it with `as_f64`, so every
|
|
62
|
+
* typed caller that obeyed this file got hash 0 — silently, on
|
|
63
|
+
* the wrong channel. Out of `0..=65535` is now an error, not a
|
|
64
|
+
* saturating cast.
|
|
65
|
+
*/
|
|
66
|
+
channelHash?: number;
|
|
67
|
+
/**
|
|
68
|
+
* The node the stream addresses: **16 hex digits**, the spelling
|
|
69
|
+
* `node_id_hex()` hands out and the four §9 peer methods take.
|
|
70
|
+
* Absent, the stream addresses the anchor — the behaviour every
|
|
71
|
+
* caller had before this option existed.
|
|
72
|
+
*
|
|
73
|
+
* A decimal id is refused rather than accepted as a second
|
|
74
|
+
* spelling, exactly as `connectPeer` refuses one.
|
|
75
|
+
*/
|
|
76
|
+
peer?: string;
|
|
77
|
+
/**
|
|
78
|
+
* **Ride the lossy carrier** — for high-rate state where only the newest
|
|
79
|
+
* value matters (positions, inputs). With `reliability: 'fireAndForget'`
|
|
80
|
+
* only; `true` with `'reliable'` throws.
|
|
81
|
+
*
|
|
82
|
+
* Every stream normally shares one ordered, fully retransmitted
|
|
83
|
+
* DataChannel, so one lost packet delays everything behind it. A lossy
|
|
84
|
+
* stream's packets ride a second, unordered channel with no
|
|
85
|
+
* retransmits: each arrives promptly or not at all, and none delays
|
|
86
|
+
* anything else. A packet that would queue behind a backed-up buffer is
|
|
87
|
+
* dropped instead (it would be stale on arrival). The receiver sees a
|
|
88
|
+
* fire-and-forget stream as always: gaps are skipped and anything older
|
|
89
|
+
* than what it already delivered is dropped — the newest value wins.
|
|
90
|
+
*
|
|
91
|
+
* Direct `connect()` nodes only for now: {@link MeshSession.openStream}
|
|
92
|
+
* refuses it. A peer or anchor that opens no lossy channel still gets
|
|
93
|
+
* the packets, on the reliable one.
|
|
94
|
+
*/
|
|
95
|
+
lossy?: boolean;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* What a stream's `on_message` callback receives from Rust.
|
|
99
|
+
*
|
|
100
|
+
* The wasm boundary hands over **the node's `stream_data` event
|
|
101
|
+
* JSON string**, the same text `on_event` delivers, filtered to this
|
|
102
|
+
* stream's id:
|
|
103
|
+
*
|
|
104
|
+
* ```json
|
|
105
|
+
* {"type":"stream_data","stream_id":"9","seq":"1","payload":"AQI="}
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* `stream_id`/`seq` are decimal `u64` strings, `payload` is padded
|
|
109
|
+
* base64. {@link LeafStream} decodes it, which is where the promise
|
|
110
|
+
* of `Uint8Array` is kept; this declaration states what actually
|
|
111
|
+
* arrives. Before Stage 5's repair it said `Uint8Array` and the
|
|
112
|
+
* string was handed to pages verbatim.
|
|
113
|
+
*
|
|
114
|
+
* `Uint8Array` is admitted as already-decoded payload for a host
|
|
115
|
+
* that supplies its own {@link LeafWasmStreamLike} — the wrapper is
|
|
116
|
+
* a public type — and it is what keeps the plain-bytes path honest
|
|
117
|
+
* in the ABI probes.
|
|
118
|
+
*/
|
|
119
|
+
export type StreamCallbackPayload = string | Uint8Array;
|
|
120
|
+
/** The stream object `open_stream` returns. */
|
|
121
|
+
export interface LeafWasmStream {
|
|
122
|
+
/** Synchronous on the Rust side: one payload, one packet, no framing. */
|
|
123
|
+
send(payload: Uint8Array): void;
|
|
124
|
+
on_message(callback: (event: StreamCallbackPayload) => void): void;
|
|
125
|
+
is_reliable(): boolean;
|
|
126
|
+
/** 16 lowercase hex digits. The event JSON's `stream_id` is the same id in decimal. */
|
|
127
|
+
stream_id_hex(): string;
|
|
128
|
+
/**
|
|
129
|
+
* The peer this stream addresses, 16 lowercase hex digits — the
|
|
130
|
+
* same spelling as {@link LeafWasmStream.stream_id_hex} on
|
|
131
|
+
* purpose, so peer and id are reconciled against their decimal
|
|
132
|
+
* event fields by one idiom rather than two. The event JSON's
|
|
133
|
+
* `peer_node` is this value in decimal.
|
|
134
|
+
*
|
|
135
|
+
* **Why the wrapper needs it:** a stream id is an application
|
|
136
|
+
* label scoped to a session, so two streams to two peers under one
|
|
137
|
+
* id is the ordinary case, not a collision. The callback delivers
|
|
138
|
+
* the NODE-WIDE event vector, so without the peer a wrapper's
|
|
139
|
+
* filter admits the other peer's payload (R4-10).
|
|
140
|
+
*
|
|
141
|
+
* **Required**, on both this and the proxied handle: the leaf
|
|
142
|
+
* implements it on both, so a consumer never has to know which kind
|
|
143
|
+
* of stream it holds to filter by peer. A host-supplied wrapper
|
|
144
|
+
* that genuinely has no peer to report is handled by the wrapper's
|
|
145
|
+
* own `identity: 'optional'` construction (`stream.ts`), not by
|
|
146
|
+
* making the boundary lie about what the leaf exposes.
|
|
147
|
+
*/
|
|
148
|
+
peer_node_hex(): string;
|
|
149
|
+
/**
|
|
150
|
+
* Which incarnation of that peer's session this stream belongs to,
|
|
151
|
+
* exact decimal — the event JSON's `incarnation`, same spelling.
|
|
152
|
+
*
|
|
153
|
+
* Provenance, not identity: the filter is `(peer, stream id)`.
|
|
154
|
+
* Send-side staleness is fenced by the leaf itself, and a replaced
|
|
155
|
+
* session retires its receive cursors, so no frame reaches a
|
|
156
|
+
* wrapper under a dead incarnation. Declared because this file is
|
|
157
|
+
* the record of the boundary the leaf actually exposes.
|
|
158
|
+
*/
|
|
159
|
+
incarnation(): string;
|
|
160
|
+
close(): void;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* The stream object a **session**'s `open_stream` resolves to.
|
|
164
|
+
*
|
|
165
|
+
* `send` is a promise because on a follower the packet is put on the
|
|
166
|
+
* wire by another tab, and `on_message` delivers the same event JSON,
|
|
167
|
+
* so one decoder serves both.
|
|
168
|
+
*
|
|
169
|
+
* **It is not otherwise identical, and the difference matters.** The
|
|
170
|
+
* real `ProxyStream` exports no `peer_node_hex` or `incarnation`
|
|
171
|
+
* (`leaf/src/leader_session.rs`), which is why they are optional
|
|
172
|
+
* here — and why a proxied stream's peer filter in `stream.ts` is
|
|
173
|
+
* inert: `peerId` reads `null` and admission falls back to the stream
|
|
174
|
+
* id alone. That is the cross-peer admixture the direct path fixed,
|
|
175
|
+
* still open for followers (S7 brief §4a). The optionality is a
|
|
176
|
+
* faithful declaration of today's ABI, not an invitation to rely on
|
|
177
|
+
* it: a consumer that needs the peer must not accept a proxied
|
|
178
|
+
* stream until the accessor exists.
|
|
179
|
+
*/
|
|
180
|
+
export interface LeafWasmProxyStream {
|
|
181
|
+
send(payload: Uint8Array): Promise<void>;
|
|
182
|
+
on_message(callback: (event: StreamCallbackPayload) => void): void;
|
|
183
|
+
is_reliable(): boolean;
|
|
184
|
+
stream_id_hex(): string;
|
|
185
|
+
/**
|
|
186
|
+
* As {@link LeafWasmStream.peer_node_hex}, and **required**.
|
|
187
|
+
*
|
|
188
|
+
* It was optional, and `ProxyStream` did not implement it, so a
|
|
189
|
+
* proxied stream's peer filter went inert and admitted any peer's
|
|
190
|
+
* frame under a matching id. The declaration is required now
|
|
191
|
+
* because the implementation exists on both handles; a consumer
|
|
192
|
+
* must not have to know which kind of stream it holds to filter by
|
|
193
|
+
* peer.
|
|
194
|
+
*/
|
|
195
|
+
peer_node_hex(): string;
|
|
196
|
+
/** As {@link LeafWasmStream.incarnation}. */
|
|
197
|
+
incarnation(): string;
|
|
198
|
+
close(): void;
|
|
199
|
+
}
|
|
200
|
+
/** Either stream object, since the wrapper serves both. */
|
|
201
|
+
export type LeafWasmStreamLike = LeafWasmStream | LeafWasmProxyStream;
|
|
202
|
+
/**
|
|
203
|
+
* The caller attribution one handler invocation receives: the crate's
|
|
204
|
+
* `to_json` JSON **string** (the `on_event` convention), camelCase
|
|
205
|
+
* keys verbatim {@link OrgCaller}'s, `entity` as 64 hex digits. Parsed
|
|
206
|
+
* once in the wrapper by {@link parseOrgCaller}.
|
|
207
|
+
*/
|
|
208
|
+
export type LeafWasmOrgCaller = string;
|
|
209
|
+
/** The credential set one org call presents. Byte fields must be real `Uint8Array`s. */
|
|
210
|
+
export interface LeafWasmOrgCredentials {
|
|
211
|
+
/** The caller's membership certificate, its 156-byte wire form. */
|
|
212
|
+
membership: Uint8Array;
|
|
213
|
+
/** The dispatcher grant, its wire form. */
|
|
214
|
+
dispatcher: Uint8Array;
|
|
215
|
+
/** The capability grant, its wire form, when the call carries one. */
|
|
216
|
+
capabilityGrant?: Uint8Array;
|
|
217
|
+
/** The org the caller acts as. */
|
|
218
|
+
actingOrg: string;
|
|
219
|
+
/** The org that owns the provider. */
|
|
220
|
+
providerOwnerOrg: string;
|
|
221
|
+
/** The provider, exactly as the call addresses it. */
|
|
222
|
+
provider: string;
|
|
223
|
+
/** Proof freshness bound, seconds. */
|
|
224
|
+
proofTtlSecs?: number;
|
|
225
|
+
}
|
|
226
|
+
/** `call_org*`'s options object. */
|
|
227
|
+
export interface LeafWasmOrgCallOptions {
|
|
228
|
+
credentials: LeafWasmOrgCredentials;
|
|
229
|
+
/**
|
|
230
|
+
* The call's deadline, milliseconds.
|
|
231
|
+
*/
|
|
232
|
+
deadlineMs?: number;
|
|
233
|
+
/**
|
|
234
|
+
* Initial response-direction flow-control window, **chunk
|
|
235
|
+
* credits** — one credit permits one item frame (the wire header's
|
|
236
|
+
* unit). NOT bytes.
|
|
237
|
+
*/
|
|
238
|
+
streamWindowInitial?: number;
|
|
239
|
+
/**
|
|
240
|
+
* Initial request-direction flow-control window, **chunk credits**
|
|
241
|
+
* (as {@link LeafWasmOrgCallOptions.streamWindowInitial}).
|
|
242
|
+
*/
|
|
243
|
+
requestWindowInitial?: number;
|
|
244
|
+
}
|
|
245
|
+
/** `serve_org*`'s options object. */
|
|
246
|
+
export interface LeafWasmOrgServeOptions {
|
|
247
|
+
/** The org that owns the provider side of every admitted call. */
|
|
248
|
+
ownerOrg: string;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Which authority admits a served call: `'same-org'` (owner-org
|
|
252
|
+
* traffic only) or `'granted'` (capability grants too). Anything else
|
|
253
|
+
* is a loud refusal at registration.
|
|
254
|
+
*/
|
|
255
|
+
export type LeafWasmOrgAccess = 'same-org' | 'granted';
|
|
256
|
+
/**
|
|
257
|
+
* One terminal item's typed error, exactly as it crosses: the frozen
|
|
258
|
+
* `kind` vocabulary plus its fields. `message` is the Display text,
|
|
259
|
+
* verbatim.
|
|
260
|
+
*/
|
|
261
|
+
export interface LeafWasmOrgTerminalError {
|
|
262
|
+
kind: string;
|
|
263
|
+
message?: string;
|
|
264
|
+
coarse?: string;
|
|
265
|
+
/** Exact decimal u64 — never a JS number. */
|
|
266
|
+
generation?: string;
|
|
267
|
+
status?: number;
|
|
268
|
+
deadlineMs?: number;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* What `OrgByteStreamHandle.next()` resolves — the leaf's three item
|
|
272
|
+
* objects (`org_stream_item` / `org_stream_end` /
|
|
273
|
+
* `org_stream_end_value` / `org_stream_end_error` in
|
|
274
|
+
* `leaf/src/wasm.rs`), verbatim. The `done` arm carries `value` when
|
|
275
|
+
* the terminal carries a final body (the completion frame's non-empty
|
|
276
|
+
* body): `{ done: true, value }`, never both `value` and `error`.
|
|
277
|
+
*/
|
|
278
|
+
export type LeafWasmOrgByteItem = {
|
|
279
|
+
done: false;
|
|
280
|
+
value: Uint8Array;
|
|
281
|
+
} | {
|
|
282
|
+
done: true;
|
|
283
|
+
value?: Uint8Array;
|
|
284
|
+
error?: LeafWasmOrgTerminalError;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* What `OrgRequestStreamHandle.next()` resolves. No error arm: a
|
|
288
|
+
* handler-side request stream's termination is observed ONLY through
|
|
289
|
+
* `retired()`.
|
|
290
|
+
*/
|
|
291
|
+
export type LeafWasmOrgRequestItem = {
|
|
292
|
+
done: false;
|
|
293
|
+
value: Uint8Array;
|
|
294
|
+
} | {
|
|
295
|
+
done: true;
|
|
296
|
+
value?: undefined;
|
|
297
|
+
};
|
|
298
|
+
/** The response half of an org call, as a raw handle. */
|
|
299
|
+
export interface LeafWasmOrgByteStreamHandle {
|
|
300
|
+
next(): Promise<LeafWasmOrgByteItem>;
|
|
301
|
+
/** Drop this caller handle: at most one CANCEL leaves per handle. */
|
|
302
|
+
cancel(): void;
|
|
303
|
+
}
|
|
304
|
+
/** A client-streaming upload, as a raw handle. */
|
|
305
|
+
export interface LeafWasmOrgUploadCallHandle {
|
|
306
|
+
send(payload: Uint8Array): Promise<void>;
|
|
307
|
+
finish(): Promise<Uint8Array>;
|
|
308
|
+
cancel(): void;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* A duplex call, as a raw handle: the sink verbs are inline (the
|
|
312
|
+
* caller-side sink has `finish_sending`/`cancel` and NO `retired` —
|
|
313
|
+
* it differs from the serve-side {@link LeafWasmOrgResponseSinkHandle},
|
|
314
|
+
* which has `close`/`retired` and no `finish_sending`).
|
|
315
|
+
*/
|
|
316
|
+
export interface LeafWasmOrgDuplexCallHandle {
|
|
317
|
+
send(payload: Uint8Array): Promise<void>;
|
|
318
|
+
finish_sending(): Promise<void>;
|
|
319
|
+
cancel(): void;
|
|
320
|
+
stream(): LeafWasmOrgByteStreamHandle;
|
|
321
|
+
}
|
|
322
|
+
/** The response sink a streaming/duplex **handler** receives. */
|
|
323
|
+
export interface LeafWasmOrgResponseSinkHandle {
|
|
324
|
+
send(payload: Uint8Array): Promise<void>;
|
|
325
|
+
close(): Promise<void>;
|
|
326
|
+
/** Resolves with exactly one of the seven retire verdict strings. */
|
|
327
|
+
retired(): Promise<string>;
|
|
328
|
+
}
|
|
329
|
+
/** The request stream a client-streaming/duplex **handler** receives. */
|
|
330
|
+
export interface LeafWasmOrgRequestStreamHandle {
|
|
331
|
+
next(): Promise<LeafWasmOrgRequestItem>;
|
|
332
|
+
/** Resolves with exactly one of the seven retire verdict strings. */
|
|
333
|
+
retired(): Promise<string>;
|
|
334
|
+
}
|
|
335
|
+
/** One serve registration, as a raw handle. */
|
|
336
|
+
export interface LeafWasmOrgServeHandle {
|
|
337
|
+
service(): string;
|
|
338
|
+
/**
|
|
339
|
+
* Unregister AND retire: every live protected call this
|
|
340
|
+
* registration admitted is retired with its exact terminal, and new
|
|
341
|
+
* openings on the service are refused. NOT the public path's
|
|
342
|
+
* let-existing-calls-finish behavior.
|
|
343
|
+
*/
|
|
344
|
+
close(): void;
|
|
345
|
+
}
|
|
346
|
+
/** The trampoline `serve_org` hands the leaf for one unary call. */
|
|
347
|
+
export type LeafWasmOrgUnaryHandler = (caller: LeafWasmOrgCaller, request: Uint8Array) => Promise<Uint8Array>;
|
|
348
|
+
/** The trampoline `serve_org_streaming` hands the leaf. */
|
|
349
|
+
export type LeafWasmOrgStreamingHandler = (caller: LeafWasmOrgCaller, request: Uint8Array, sink: LeafWasmOrgResponseSinkHandle) => Promise<void>;
|
|
350
|
+
/** The trampoline `serve_org_client_stream` hands the leaf. */
|
|
351
|
+
export type LeafWasmOrgClientStreamHandler = (caller: LeafWasmOrgCaller, requests: LeafWasmOrgRequestStreamHandle) => Promise<Uint8Array>;
|
|
352
|
+
/** The trampoline `serve_org_duplex` hands the leaf. */
|
|
353
|
+
export type LeafWasmOrgDuplexHandler = (caller: LeafWasmOrgCaller, requests: LeafWasmOrgRequestStreamHandle, sink: LeafWasmOrgResponseSinkHandle) => Promise<void>;
|
|
354
|
+
/** The node object `LeafNode.connect` resolves to. */
|
|
355
|
+
export interface LeafWasmNode {
|
|
356
|
+
node_id_hex(): string;
|
|
357
|
+
/** The anchor's node id, 16 lowercase hex digits. */
|
|
358
|
+
anchor_id_hex(): string;
|
|
359
|
+
/**
|
|
360
|
+
* This node's origin hash, 16 lowercase hex digits — the value its
|
|
361
|
+
* packet headers carry and the one a receiver checks an event
|
|
362
|
+
* payload's `EventMeta.origin_hash` against.
|
|
363
|
+
*/
|
|
364
|
+
origin_hash_hex(): string;
|
|
365
|
+
/**
|
|
366
|
+
* Run the enrollment exchange. `connect` awaits it internally after
|
|
367
|
+
* the handshake; the explicit method exists so a caller can drive or
|
|
368
|
+
* observe the step. Until a leaf is enrolled the anchor keeps the
|
|
369
|
+
* peer provisional and §12 refuses everything above the transport.
|
|
370
|
+
*/
|
|
371
|
+
enroll(): Promise<void>;
|
|
372
|
+
/**
|
|
373
|
+
* Whether the anchor has admitted this leaf. `false` means the
|
|
374
|
+
* session is still §12-provisional and every call will die on its
|
|
375
|
+
* deadline, which is a very different fact from a slow anchor.
|
|
376
|
+
*/
|
|
377
|
+
is_enrolled(): boolean;
|
|
378
|
+
call(service: string, payload: Uint8Array, timeout_ms?: number): Promise<Uint8Array>;
|
|
379
|
+
call_org(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<Uint8Array>;
|
|
380
|
+
call_org_streaming(service: string, payload: Uint8Array, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgByteStreamHandle>;
|
|
381
|
+
call_org_client_stream(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgUploadCallHandle>;
|
|
382
|
+
call_org_duplex(service: string, options: LeafWasmOrgCallOptions): Promise<LeafWasmOrgDuplexCallHandle>;
|
|
383
|
+
/**
|
|
384
|
+
* Serve the four shapes. The handler is invoked with `(caller,
|
|
385
|
+
* request[, requests][, sink])` per shape and returns a promise the
|
|
386
|
+
* leaf awaits; a rejection is the typed refusal text.
|
|
387
|
+
*/
|
|
388
|
+
serve_org(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgUnaryHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
389
|
+
serve_org_streaming(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgStreamingHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
390
|
+
serve_org_client_stream(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgClientStreamHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
391
|
+
serve_org_duplex(service: string, access: LeafWasmOrgAccess, handler: LeafWasmOrgDuplexHandler, options: LeafWasmOrgServeOptions): LeafWasmOrgServeHandle;
|
|
392
|
+
subscribe(channel: string): Promise<void>;
|
|
393
|
+
publish(channel: string, payload: Uint8Array): Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Open a stream on this node.
|
|
396
|
+
*
|
|
397
|
+
* **Throws on a closed node.** `Inner::admit` fences every
|
|
398
|
+
* outbound operation once `close()` (or a leadership retirement)
|
|
399
|
+
* has run, with the `LeafError::Session` Display
|
|
400
|
+
* `session: the node is closed: it no longer holds this origin's
|
|
401
|
+
* identity` — so the refusal arrives as a `SessionError` through
|
|
402
|
+
* `fromWasmError` rather than as a silent dead handle. Declared
|
|
403
|
+
* here because it is the contract `BrowserNode.openStream` relies
|
|
404
|
+
* on instead of adding a second fence of its own; the text is
|
|
405
|
+
* pinned against `leaf/src/wasm.rs` by
|
|
406
|
+
* `tests/abi_real_package.mjs`.
|
|
407
|
+
*/
|
|
408
|
+
open_stream(options: LeafWasmStreamOptions): LeafWasmStream;
|
|
409
|
+
announce(capabilities: string[]): Promise<void>;
|
|
410
|
+
/**
|
|
411
|
+
* A JSON array of `{ node_id, entity_id, capabilities, rtc_addr,
|
|
412
|
+
* noise_pubkey, version }`.
|
|
413
|
+
*/
|
|
414
|
+
query(capability: string): Promise<string>;
|
|
415
|
+
/**
|
|
416
|
+
* Sign and send a `0x0D02` signalling envelope to `peer` through the
|
|
417
|
+
* control plane — no session with `peer` needed.
|
|
418
|
+
*
|
|
419
|
+
* `dialog_hex` is the attempt's id, 16 lowercase hex digits — the
|
|
420
|
+
* same spelling {@link LeafWasmNode.peer_offer} resolves to and the
|
|
421
|
+
* `*_in` forms take. A number would not do: `DialogId` is a `u64`
|
|
422
|
+
* minted from the full CSPRNG range, and one carried through a JS
|
|
423
|
+
* number comes back rounded (`as f64 as u64`), so ~511 of every 512
|
|
424
|
+
* minted dialogs would name no attempt at all.
|
|
425
|
+
*
|
|
426
|
+
* Both id arguments cross as STRINGS, verbatim — {@link idArg} is
|
|
427
|
+
* the marshaling. A non-string is refused
|
|
428
|
+
* "is not a peer id" / "is not a dialog id" at the binding rather
|
|
429
|
+
* than coerced, and rather than reaching `wasm-bindgen`'s String
|
|
430
|
+
* marshaling at all: a JS number here corrupts `passStringToWasm0`
|
|
431
|
+
* (panicking `assert!(old_size > 0)` in `__wbindgen_realloc`) and
|
|
432
|
+
* kills the call before any parser runs — finding #52's
|
|
433
|
+
* engine-marshaling failure, on every peer spelling alike.
|
|
434
|
+
*/
|
|
435
|
+
signal(peer_hex: string, dialog_hex: string, kind: string, payload: Uint8Array): Promise<void>;
|
|
436
|
+
/**
|
|
437
|
+
* Offer a direct browser ↔ browser connection to `peer` (plan §9
|
|
438
|
+
* steps 2–3). Resolves to the dialog id, 16 lowercase hex digits.
|
|
439
|
+
*
|
|
440
|
+
* Takes a peer id. The SDP is created, signed and sent inside the
|
|
441
|
+
* leaf; the relayed session it rides comes up first if it is not
|
|
442
|
+
* already there.
|
|
443
|
+
*/
|
|
444
|
+
peer_offer(peer_hex: string): Promise<string>;
|
|
445
|
+
/**
|
|
446
|
+
* The live attempt's dialog when `peer` is already a healthy direct
|
|
447
|
+
* pair (session installed, no relay entry, transport open), else
|
|
448
|
+
* `undefined`. What makes `connectPeer` idempotent: a second offer
|
|
449
|
+
* would replace — and close — the working link.
|
|
450
|
+
*/
|
|
451
|
+
peer_direct_dialog(peer_hex: string): string | undefined;
|
|
452
|
+
/**
|
|
453
|
+
* Answer the offer `peer` sent, from the **verified envelope** that
|
|
454
|
+
* arrived — not from anything the caller supplies. Resolves to the
|
|
455
|
+
* dialog id the offerer minted.
|
|
456
|
+
*/
|
|
457
|
+
peer_accept_offer(peer_hex: string): Promise<string>;
|
|
458
|
+
/**
|
|
459
|
+
* Service `peer`'s attempt once: apply its answer, trickle local
|
|
460
|
+
* candidates as signed envelopes, apply the ones it sent, and
|
|
461
|
+
* evaluate the attempt's deadline.
|
|
462
|
+
*
|
|
463
|
+
* Resolves to JSON: `{"dialog","state","sent","applied","answered",
|
|
464
|
+
* "direct","remainingMs"}`, plus `"candidateError"` when the engine
|
|
465
|
+
* refused a trickled line. `state` is `gathering | open |
|
|
466
|
+
* iceTimeout | udpBlocked | failed`; `failed` is the attempt's
|
|
467
|
+
* terminal transition for a channel that opened and a session that
|
|
468
|
+
* never installed. `dialog` is the attempt CURRENTLY live for the
|
|
469
|
+
* peer, so a caller whose dialog id no longer matches was
|
|
470
|
+
* superseded.
|
|
471
|
+
*/
|
|
472
|
+
peer_candidate(peer_hex: string): Promise<string>;
|
|
473
|
+
/**
|
|
474
|
+
* Run the Noise handshake with `peer` over the direct DataChannel
|
|
475
|
+
* (§9 step 4), in the offerer's role. Resolves to the dialog id it
|
|
476
|
+
* ran for, 16 lowercase hex digits.
|
|
477
|
+
*
|
|
478
|
+
* **A peer id and nothing else.** A page that could supply a Noise
|
|
479
|
+
* key could supply any key, so the peer's static key comes from its
|
|
480
|
+
* signature-verified announcement and the PSK from the credential.
|
|
481
|
+
*
|
|
482
|
+
* The resolved dialog is what makes a stale caller's success
|
|
483
|
+
* legible: it is the attempt the handshake actually ran for, not
|
|
484
|
+
* the one the caller was holding.
|
|
485
|
+
*/
|
|
486
|
+
peer_handshake(peer_hex: string): Promise<string>;
|
|
487
|
+
/**
|
|
488
|
+
* {@link LeafWasmNode.peer_candidate}, for a caller that names the
|
|
489
|
+
* dialog it is driving.
|
|
490
|
+
*
|
|
491
|
+
* Refused when that dialog is not the live one, **before** the
|
|
492
|
+
* attempt is serviced — so a request issued for an attempt that has
|
|
493
|
+
* since been replaced cannot drive its replacement. The shared
|
|
494
|
+
* drive loop uses this form on both surfaces.
|
|
495
|
+
*/
|
|
496
|
+
peer_candidate_in(peer_hex: string, dialog_hex: string): Promise<string>;
|
|
497
|
+
/**
|
|
498
|
+
* {@link LeafWasmNode.peer_handshake}, for a caller that names the
|
|
499
|
+
* dialog it is driving. Refused on a mismatch, before the Noise
|
|
500
|
+
* wait — the longest await on this surface, and the one whose
|
|
501
|
+
* session must belong to the attempt that negotiated the channel.
|
|
502
|
+
*/
|
|
503
|
+
peer_handshake_in(peer_hex: string, dialog_hex: string): Promise<string>;
|
|
504
|
+
/** Every counter as JSON; `u64`s are decimal strings. */
|
|
505
|
+
counters_json(): string;
|
|
506
|
+
/**
|
|
507
|
+
* The RTC transport's `RtcStats` as JSON, in the NATIVE field
|
|
508
|
+
* names, plus a `not_applicable` object mapping each native field
|
|
509
|
+
* a leaf has no meaning for to the reason it has none.
|
|
510
|
+
*/
|
|
511
|
+
rtc_stats_json(): string;
|
|
512
|
+
/**
|
|
513
|
+
* Install the `online` listener for the network-change re-attempt
|
|
514
|
+
* trigger. Idempotent; the ICE `disconnected` → `failed` watcher
|
|
515
|
+
* is already on every peer connection.
|
|
516
|
+
*/
|
|
517
|
+
arm_network_retry(): void;
|
|
518
|
+
/** The re-attempt owner's ledger as JSON. */
|
|
519
|
+
retry_report(): string;
|
|
520
|
+
/** One JSON-string event per call. Registered once per node. */
|
|
521
|
+
on_event(callback: (eventJson: string) => void): void;
|
|
522
|
+
/**
|
|
523
|
+
* Close the node: every session, every channel, every pending
|
|
524
|
+
* call.
|
|
525
|
+
*
|
|
526
|
+
* After it, nothing is delivered and every outbound operation is
|
|
527
|
+
* refused — which is why `BrowserNode.close` closes the
|
|
528
|
+
* streams it handed out **before** calling this, rather than
|
|
529
|
+
* leaving their handles to be retired through a node that would
|
|
530
|
+
* only report the attempt as a failure.
|
|
531
|
+
*/
|
|
532
|
+
close(): void;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* The module `wasm-bindgen --target web` generates.
|
|
536
|
+
*
|
|
537
|
+
* `MeshSession` is typed as `unknown` here on purpose: §8's
|
|
538
|
+
* leader/follower boundary lives in `src/leader/wasm.ts`, which owns
|
|
539
|
+
* its shape. This file keeps only what the direct surface needs, so
|
|
540
|
+
* the two cannot drift into two spellings of one contract.
|
|
541
|
+
*/
|
|
542
|
+
export interface LeafWasmModule {
|
|
543
|
+
/**
|
|
544
|
+
* The generated initialiser. Instantiates the `.wasm` next to the
|
|
545
|
+
* glue unless given a path or module.
|
|
546
|
+
*/
|
|
547
|
+
default?: (init?: {
|
|
548
|
+
module_or_path: string | URL;
|
|
549
|
+
}) => Promise<unknown>;
|
|
550
|
+
LeafNode: {
|
|
551
|
+
connect(options: LeafWasmConnectOptions): Promise<LeafWasmNode>;
|
|
552
|
+
/**
|
|
553
|
+
* The ICE servers a `connect()` with these options would hand
|
|
554
|
+
* the `RTCPeerConnection`, as JSON:
|
|
555
|
+
* `[{"urls":["stun:host:3478"],"username":"u","credential":"c"}]`.
|
|
556
|
+
*
|
|
557
|
+
* Static and pure, so the ABI it reports can be asserted
|
|
558
|
+
* against the real built wasm without an anchor — which is the
|
|
559
|
+
* only reason the `RTCIceServer[]` drop went unnoticed. Throws
|
|
560
|
+
* the same typed error `connect()` would.
|
|
561
|
+
*
|
|
562
|
+
* Optional because {@link loadLeafWasm} will happily load a glue
|
|
563
|
+
* built before this existed; `tests/abi_real_package.mjs`
|
|
564
|
+
* asserts the shipped one has it.
|
|
565
|
+
*/
|
|
566
|
+
effective_ice_servers?(options: LeafWasmConnectOptions): string;
|
|
567
|
+
/**
|
|
568
|
+
* The largest payload one packet carries: the wire's
|
|
569
|
+
* `MAX_EVENT_SIZE`, which is `MAX_PAYLOAD_SIZE` minus the event
|
|
570
|
+
* frame's 4-byte length prefix.
|
|
571
|
+
*
|
|
572
|
+
* An application that must keep a message inside one packet
|
|
573
|
+
* reads it from here rather than hardcoding a figure. The packet
|
|
574
|
+
* cap is **not** this number, and treating it as available data
|
|
575
|
+
* bytes overruns by the prefix.
|
|
576
|
+
*
|
|
577
|
+
* Optional for the same reason `effective_ice_servers` is: glue
|
|
578
|
+
* built before this existed still loads, and
|
|
579
|
+
* `tests/abi_real_package.mjs` asserts the shipped one has it.
|
|
580
|
+
*/
|
|
581
|
+
maxEventBytes?(): number;
|
|
582
|
+
/**
|
|
583
|
+
* What an `open_stream()` with these options would ask the node
|
|
584
|
+
* for, as JSON: `{"reliability":"reliable","label":"app",
|
|
585
|
+
* "streamId":"0000000000000009","channelHash":7,
|
|
586
|
+
* "peer":"00366d403ce19dac"}`, `streamId` `null` when unpinned,
|
|
587
|
+
* `channelHash` `null` when absent, `peer` `null` when the
|
|
588
|
+
* stream addresses the anchor.
|
|
589
|
+
*
|
|
590
|
+
* The same reader `MeshSession.open_stream` uses, so one
|
|
591
|
+
* assertion covers the direct and the leader-proxied surface —
|
|
592
|
+
* which is also why `peer` appears here: the proxied surface
|
|
593
|
+
* refuses that option by name, and this is where a page can see
|
|
594
|
+
* what the leaf made of it.
|
|
595
|
+
*
|
|
596
|
+
* Optional for the same reason as the reader above.
|
|
597
|
+
*/
|
|
598
|
+
effective_stream_options?(options: LeafWasmStreamOptions): string;
|
|
599
|
+
};
|
|
600
|
+
/**
|
|
601
|
+
* §8's surface, refined by `src/leader/wasm.ts`. Absent from a
|
|
602
|
+
* bundle built before Stage 5 slice 3.
|
|
603
|
+
*/
|
|
604
|
+
MeshSession?: unknown;
|
|
605
|
+
}
|
|
606
|
+
/** Where the wasm comes from. */
|
|
607
|
+
export interface WasmSource {
|
|
608
|
+
/**
|
|
609
|
+
* An already-imported module. The escape hatch for bundlers, for
|
|
610
|
+
* tests, and for a page that wants to control instantiation.
|
|
611
|
+
*/
|
|
612
|
+
wasm?: LeafWasmModule;
|
|
613
|
+
/**
|
|
614
|
+
* A specifier or URL to `import()`. Defaults to `./net_leaf.js`
|
|
615
|
+
* resolved against this module, i.e. the glue `npm run build`
|
|
616
|
+
* copies next to the entry point.
|
|
617
|
+
*/
|
|
618
|
+
wasmModule?: string;
|
|
619
|
+
/** The `.wasm` to instantiate. Defaults to the glue's own sibling. */
|
|
620
|
+
wasmUrl?: string | URL;
|
|
621
|
+
}
|
|
622
|
+
/** Resolve and instantiate the leaf wasm described by `source`. */
|
|
623
|
+
export declare function loadLeafWasm(source?: WasmSource): Promise<LeafWasmModule>;
|
|
624
|
+
/**
|
|
625
|
+
* One id argument of {@link LeafWasmNode.signal} as it crosses the
|
|
626
|
+
* wasm seam: a string passes through VERBATIM, and anything else is
|
|
627
|
+
* refused by the parsers' own names before it can reach the boundary.
|
|
628
|
+
*
|
|
629
|
+
* Refused, never coerced, and either alternative is fatal. A JS
|
|
630
|
+
* number cannot carry a `u64` id losslessly (`as f64 as u64`
|
|
631
|
+
* re-spells 511 of every 512 minted dialogs) — and a non-string must
|
|
632
|
+
* never reach `wasm-bindgen`'s String marshaling at all: it corrupts
|
|
633
|
+
* there, panicking `assert!(old_size > 0)` inside
|
|
634
|
+
* `passStringToWasm0`'s `__wbindgen_realloc`, and the call dies
|
|
635
|
+
* before `parse_peer_id` runs (finding #52's repro, on every peer
|
|
636
|
+
* spelling alike). The refusal carries the parser's name — "is not a
|
|
637
|
+
* peer id" / "is not a dialog id", as `name` picks — so a page that
|
|
638
|
+
* classifies a refusal by its text reads this one as the refusal it
|
|
639
|
+
* is. Peer before dialog at the call sites, the order
|
|
640
|
+
* `LeafNode::signal` parses in.
|
|
641
|
+
*/
|
|
642
|
+
export declare function idArg(value: unknown, name: 'peer' | 'dialog'): string;
|