@inkly/webtransport
v0.0.0
Published
WebTransport (HTTP/3) transport bridge for inkly — adapt a W3C WebTransport session to inkly's Connection seam.
Readme
@inkly/webtransport
WebTransport (HTTP/3 / QUIC) transport bridge for inkly.
What is WebTransport?
WebTransport is a W3C/IETF API over HTTP/3 and QUIC. It provides independent reliable bidirectional and unidirectional streams plus unreliable datagrams, all without TCP head-of-line blocking between streams.
- MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport
- W3C Specification: https://www.w3.org/TR/webtransport/
Honest server-support caveat
Server-side WebTransport is not yet broadly or natively available across Node, Bun, and
Deno. On Node it is typically provided by third-party libraries such as
@fails-components/webtransport; some edge runtimes are adding it natively.
This package is therefore a runtime-agnostic bridge: it accepts whatever WebTransport
session object a runtime or library hands you (structurally typed as
WebTransportLikeSession) and adapts it to inkly's Connection/AdapterHandlers model.
This lets inkly apps run over WebTransport with no application-layer API change, and lets
a native backend land later without breaking anything.
Install
pnpm add @inkly/webtransport @inkly/coreQuickstart
import { inkly, contract } from "@inkly/core";
import { serveWebTransport } from "@inkly/webtransport";
import type { WebTransportLikeSession } from "@inkly/webtransport";
const api = contract({ actions: { ... } });
const app = inkly(api);
// Obtain a session from your runtime/library (e.g. @fails-components/webtransport on Node):
// const session = ...; // WebTransport session from your server library
async function handleSession(session: WebTransportLikeSession): Promise<void> {
// serveWebTransport awaits the first incoming bidi stream, builds a Connection,
// calls handlers.open(), and starts the frame read loop.
const bridge = await serveWebTransport(app, session, {
remoteAddress: "127.0.0.1:12345",
});
await bridge.closed; // resolves when the session ends
}Framing format
inkly frames are carried on the first bidirectional stream using length-prefix framing:
+------ 4 bytes ------+------ N bytes ------+
| uint32 big-endian N | payload |
+---------------------+---------------------+Use frame(payload) and FrameDecoder in your test clients:
import { frame, FrameDecoder } from "@inkly/webtransport";
// Encode
const encoded = frame(JSON.stringify({ t: "hello" }));
// Decode
const decoder = new FrameDecoder();
const [payload] = decoder.push(incomingChunk);
const message = JSON.parse(new TextDecoder().decode(payload));API
| Export | Description |
|--------|-------------|
| serveWebTransport(app, session, options?) | Main entry point. Awaits first bidi stream, returns WebTransportBridge. |
| webTransportBridge | Alias for serveWebTransport. |
| frame(payload) | Encode string \| Uint8Array into a length-prefixed Uint8Array. |
| FrameDecoder | Stateful decoder: push(chunk): Uint8Array[]. |
| WebTransportLikeSession | Structural interface for the session object. |
| WebTransportLikeStream | Structural interface for a bidirectional stream. |
| WebTransportApp | { handlers: AdapterHandlers } — what inkly apps satisfy. |
| ServeWebTransportOptions | { request?, id?, remoteAddress? } |
| WebTransportBridge | { connection, closed, close(code?, reason?) } |
Caveats
- Single control stream (v1): only the first incoming bidirectional stream is used. All inkly frames travel on this stream. Datagrams and multi-stream are future work.
- You supply the session: this package does not start a server. Obtain the session
from your runtime or a library such as
@fails-components/webtransporton Node. - See
docs/overview.mdfor a deeper explanation of the framing design and the path to datagrams.
See examples/node-fails-components.ts for a full Node.js wiring example.
