@moq/web-transport 0.0.4 → 0.1.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 ADDED
@@ -0,0 +1,97 @@
1
+ # @moq/web-transport
2
+
3
+ WebTransport for Node.js, powered by QUIC and HTTP/3.
4
+
5
+ This package provides both a client-side `WebTransport` polyfill and a server implementation.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @moq/web-transport
11
+ ```
12
+
13
+ ## Client
14
+
15
+ The `Session` class implements the [W3C WebTransport API](https://www.w3.org/TR/webtransport/).
16
+
17
+ ```ts
18
+ import Session from "@moq/web-transport";
19
+
20
+ const session = new Session("https://example.com:4443");
21
+ await session.ready;
22
+
23
+ // Bidirectional streams
24
+ const bidi = await session.createBidirectionalStream();
25
+ const writer = bidi.writable.getWriter();
26
+ await writer.write(new Uint8Array([1, 2, 3]));
27
+ await writer.close();
28
+
29
+ // Unidirectional streams
30
+ const uni = await session.createUnidirectionalStream();
31
+ const uniWriter = uni.getWriter();
32
+ await uniWriter.write(new Uint8Array([4, 5, 6]));
33
+ await uniWriter.close();
34
+
35
+ // Datagrams
36
+ const dgWriter = session.datagrams.writable.getWriter();
37
+ await dgWriter.write(new Uint8Array([7, 8, 9]));
38
+
39
+ // Incoming streams
40
+ for await (const recv of session.incomingUnidirectionalStreams) {
41
+ const reader = recv.getReader();
42
+ // read from reader...
43
+ }
44
+
45
+ session.close();
46
+ ```
47
+
48
+ ### Polyfill
49
+
50
+ Use `install()` to register `Session` as the global `WebTransport` if one doesn't already exist:
51
+
52
+ ```ts
53
+ import { install } from "@moq/web-transport";
54
+ install();
55
+
56
+ // Now use the standard WebTransport API
57
+ const session = new WebTransport("https://example.com:4443");
58
+ ```
59
+
60
+ ### Certificate Options
61
+
62
+ ```ts
63
+ // Skip certificate verification (testing only!)
64
+ const session = new Session("https://localhost:4443", {
65
+ serverCertificateDisableVerify: true,
66
+ });
67
+
68
+ // Pin to specific certificate hashes
69
+ const session = new Session("https://example.com:4443", {
70
+ serverCertificateHashes: [
71
+ { algorithm: "sha-256", value: hashBuffer },
72
+ ],
73
+ });
74
+ ```
75
+
76
+ ## Server
77
+
78
+ ```ts
79
+ import { Server } from "@moq/web-transport";
80
+ import fs from "node:fs";
81
+
82
+ const certPem = fs.readFileSync("cert.pem");
83
+ const keyPem = fs.readFileSync("key.pem");
84
+
85
+ const server = Server.bind("[::]:4443", certPem, keyPem);
86
+
87
+ while (true) {
88
+ const request = await server.accept();
89
+ if (!request) break;
90
+
91
+ const url = await request.url;
92
+ console.log("incoming request:", url);
93
+
94
+ const session = await request.ok();
95
+ // Use session just like the client-side API
96
+ }
97
+ ```
@@ -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.0",
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.0",
40
+ "@moq/web-transport-darwin-arm64": "0.1.0",
41
+ "@moq/web-transport-win32-x64-msvc": "0.1.0",
42
+ "@moq/web-transport-linux-x64-gnu": "0.1.0",
43
+ "@moq/web-transport-linux-arm64-gnu": "0.1.0"
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