@moq/web-transport 0.0.4 → 0.1.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 ADDED
@@ -0,0 +1,141 @@
1
+ # @moq/web-transport
2
+
3
+ WebTransport for Node.js, powered by native QUIC/HTTP3 via NAPI-RS.
4
+
5
+ Provides a custom client and server API for setup, then exposes the standard [W3C WebTransport API](https://www.w3.org/TR/webtransport/) for streams, datagrams, and session lifecycle.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add @moq/web-transport
11
+ ```
12
+
13
+ ## Client
14
+
15
+ Connect to a WebTransport server using the `Session` class, which implements the W3C `WebTransport` interface:
16
+
17
+ ```ts
18
+ import Session from "@moq/web-transport";
19
+
20
+ const session = new Session("https://example.com:4443/path");
21
+ await session.ready;
22
+
23
+ // Use the standard W3C WebTransport API from here on
24
+ ```
25
+
26
+ ### Certificate options
27
+
28
+ ```ts
29
+ // Skip certificate verification (testing only!)
30
+ const session = new Session("https://localhost:4443", {
31
+ serverCertificateDisableVerify: true,
32
+ });
33
+
34
+ // Pin to specific certificate hashes
35
+ const session = new Session("https://localhost:4443", {
36
+ serverCertificateHashes: [
37
+ { algorithm: "sha-256", value: certHash },
38
+ ],
39
+ });
40
+ ```
41
+
42
+ ### Polyfill
43
+
44
+ Install `Session` as the global `WebTransport` for libraries that expect the browser API:
45
+
46
+ ```ts
47
+ import { install } from "@moq/web-transport";
48
+
49
+ install(); // globalThis.WebTransport = Session (no-op if already defined)
50
+ ```
51
+
52
+ ## Server
53
+
54
+ Use `Server` to accept incoming connections. Each `Request` can be accepted (returning a W3C `Session`) or rejected:
55
+
56
+ ```ts
57
+ import { Server } from "@moq/web-transport";
58
+ import fs from "node:fs";
59
+
60
+ const cert = fs.readFileSync("cert.pem");
61
+ const key = fs.readFileSync("key.pem");
62
+
63
+ const server = Server.bind("[::]:4443", cert, key);
64
+
65
+ while (true) {
66
+ const request = await server.accept();
67
+ if (!request) break;
68
+
69
+ const url = await request.url;
70
+ console.log("incoming session:", url);
71
+
72
+ const session = await request.ok(); // or request.reject(404)
73
+
74
+ // Use the standard W3C WebTransport API from here on
75
+ handleSession(session);
76
+ }
77
+
78
+ // Stop accepting new connections
79
+ server.close();
80
+ ```
81
+
82
+ ## W3C WebTransport API
83
+
84
+ Once you have a `Session` (client or server-side), the API follows the [W3C WebTransport spec](https://www.w3.org/TR/webtransport/):
85
+
86
+ ### Bidirectional streams
87
+
88
+ ```ts
89
+ // Open a bidirectional stream
90
+ const stream = await session.createBidirectionalStream();
91
+ const writer = stream.writable.getWriter();
92
+ await writer.write(new Uint8Array([1, 2, 3]));
93
+ await writer.close();
94
+
95
+ // Accept incoming bidirectional streams
96
+ const reader = session.incomingBidirectionalStreams.getReader();
97
+ const { value: incoming } = await reader.read();
98
+ const data = await new Response(incoming.readable).arrayBuffer();
99
+ ```
100
+
101
+ ### Unidirectional streams
102
+
103
+ ```ts
104
+ // Open a unidirectional stream
105
+ const writable = await session.createUnidirectionalStream();
106
+ const writer = writable.getWriter();
107
+ await writer.write(new TextEncoder().encode("hello"));
108
+ await writer.close();
109
+
110
+ // Accept incoming unidirectional streams
111
+ const reader = session.incomingUnidirectionalStreams.getReader();
112
+ const { value: readable } = await reader.read();
113
+ const text = await new Response(readable).text();
114
+ ```
115
+
116
+ ### Datagrams
117
+
118
+ ```ts
119
+ // Send datagrams
120
+ const writer = session.datagrams.writable.getWriter();
121
+ await writer.write(new Uint8Array([0x01, 0x02]));
122
+
123
+ // Receive datagrams
124
+ const reader = session.datagrams.readable.getReader();
125
+ const { value: datagram } = await reader.read();
126
+ ```
127
+
128
+ ### Closing
129
+
130
+ ```ts
131
+ // Close gracefully
132
+ session.close({ closeCode: 0, reason: "done" });
133
+
134
+ // Wait for the session to close
135
+ const info = await session.closed;
136
+ console.log(info.closeCode, info.reason);
137
+ ```
138
+
139
+ ## License
140
+
141
+ MIT OR Apache-2.0
@@ -59,6 +59,8 @@ export declare class NapiServer {
59
59
  static bind(addr: string, certPem: Buffer, keyPem: Buffer): NapiServer;
60
60
  /** Accept the next incoming WebTransport session request. */
61
61
  accept(): Promise<NapiRequest | null>;
62
+ /** Close the server, stopping it from accepting new connections. */
63
+ close(): void;
62
64
  }
63
65
 
64
66
  /** An established WebTransport session. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moq/web-transport",
3
- "version": "0.0.4",
3
+ "version": "0.1.1",
4
4
  "description": "WebTransport polyfill for Node.js via QUIC/HTTP3",
5
5
  "type": "module",
6
6
  "license": "(MIT OR Apache-2.0)",
@@ -21,12 +21,12 @@
21
21
  "types": "./src/index.ts",
22
22
  "files": [
23
23
  "./src",
24
- "index.js",
25
- "index.d.ts",
24
+ "napi.js",
25
+ "napi.d.ts",
26
26
  "*.node"
27
27
  ],
28
28
  "scripts": {
29
- "build": "napi build --platform --release --manifest-path ../../rs/web-transport-node/Cargo.toml --output-dir .",
29
+ "build": "napi build --platform --release --manifest-path ../../rs/web-transport-node/Cargo.toml --output-dir . --js napi.js --dts napi.d.ts",
30
30
  "check": "tsc --noEmit",
31
31
  "release": "bun scripts/release.ts"
32
32
  },
@@ -36,11 +36,11 @@
36
36
  "@types/node": "^24.3.0"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@moq/web-transport-darwin-x64": "0.0.4",
40
- "@moq/web-transport-darwin-arm64": "0.0.4",
41
- "@moq/web-transport-win32-x64-msvc": "0.0.4",
42
- "@moq/web-transport-linux-x64-gnu": "0.0.4",
43
- "@moq/web-transport-linux-arm64-gnu": "0.0.4"
39
+ "@moq/web-transport-darwin-x64": "0.1.1",
40
+ "@moq/web-transport-darwin-arm64": "0.1.1",
41
+ "@moq/web-transport-win32-x64-msvc": "0.1.1",
42
+ "@moq/web-transport-linux-x64-gnu": "0.1.1",
43
+ "@moq/web-transport-linux-arm64-gnu": "0.1.1"
44
44
  },
45
45
  "keywords": [
46
46
  "webtransport",
package/src/datagrams.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { NapiSession } from "../index.js";
1
+ import type { NapiSession } from "../napi.js";
2
2
 
3
3
  export class Datagrams implements WebTransportDatagramDuplexStream {
4
4
  readonly readable: ReadableStream<Uint8Array>;
package/src/index.ts CHANGED
@@ -9,4 +9,6 @@ export function install(): boolean {
9
9
  }
10
10
 
11
11
  export default Session;
12
- export { NapiRequest, NapiServer } from "../index.js";
12
+ export { Request } from "./request.ts";
13
+ export { Server } from "./server.ts";
14
+ export type { SessionOptions } from "./session.ts";
package/src/request.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { NapiRequest } from "../napi.js";
2
+ import Session from "./session.ts";
3
+
4
+ export class Request {
5
+ #inner: NapiRequest;
6
+
7
+ /** @internal */
8
+ constructor(inner: NapiRequest) {
9
+ this.#inner = inner;
10
+ }
11
+
12
+ get url(): Promise<string> {
13
+ return this.#inner.url;
14
+ }
15
+
16
+ async ok(): Promise<Session> {
17
+ const session = await this.#inner.ok();
18
+ return new Session(session);
19
+ }
20
+
21
+ reject(status: number): Promise<void> {
22
+ return this.#inner.reject(status);
23
+ }
24
+ }
package/src/server.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { NapiServer } from "../napi.js";
2
+ import { Request } from "./request.ts";
3
+
4
+ export class Server {
5
+ #inner: NapiServer;
6
+
7
+ private constructor(inner: NapiServer) {
8
+ this.#inner = inner;
9
+ }
10
+
11
+ static bind(addr: string, certPem: Buffer, keyPem: Buffer): Server {
12
+ return new Server(NapiServer.bind(addr, certPem, keyPem));
13
+ }
14
+
15
+ async accept(): Promise<Request | null> {
16
+ const inner = await this.#inner.accept();
17
+ if (!inner) return null;
18
+ return new Request(inner);
19
+ }
20
+
21
+ close(): void {
22
+ this.#inner.close();
23
+ }
24
+ }
package/src/session.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { NapiClient, type NapiRecvStream, type NapiSendStream, type NapiSession } from "../index.js";
1
+ import { NapiClient, type NapiRecvStream, type NapiSendStream, type NapiSession } from "../napi.js";
2
2
  import { Datagrams } from "./datagrams.ts";
3
3
 
4
4
  function wrapRecvStream(recv: NapiRecvStream): ReadableStream<Uint8Array> {
Binary file
Binary file
Binary file
Binary file
Binary file
File without changes