@moq/web-transport 0.0.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/index.d.ts +90 -0
- package/index.js +746 -0
- package/package.json +52 -0
- package/src/datagrams.ts +39 -0
- package/src/index.ts +12 -0
- package/src/session.ts +264 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/* auto-generated by NAPI-RS */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/** A bidirectional stream pair. */
|
|
4
|
+
export declare class NapiBiStream {
|
|
5
|
+
/** Take the send stream. Can only be called once. */
|
|
6
|
+
takeSend(): NapiSendStream;
|
|
7
|
+
/** Take the recv stream. Can only be called once. */
|
|
8
|
+
takeRecv(): NapiRecvStream;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** A WebTransport client that can connect to servers. */
|
|
12
|
+
export declare class NapiClient {
|
|
13
|
+
/** Create a client that validates server certificates against system root CAs. */
|
|
14
|
+
static withSystemRoots(): NapiClient;
|
|
15
|
+
/**
|
|
16
|
+
* Create a client that skips certificate verification entirely.
|
|
17
|
+
* WARNING: Only use for testing with self-signed certificates.
|
|
18
|
+
*/
|
|
19
|
+
static disableVerify(): NapiClient;
|
|
20
|
+
/** Create a client that validates server certificates by SHA-256 hash. */
|
|
21
|
+
static withCertificateHashes(hashes: Array<Buffer>): NapiClient;
|
|
22
|
+
/** Connect to a WebTransport server at the given URL. */
|
|
23
|
+
connect(urlStr: string): Promise<NapiSession>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** A receive stream for reading data. */
|
|
27
|
+
export declare class NapiRecvStream {
|
|
28
|
+
/** Read up to `max_size` bytes from the stream. Returns null on FIN. */
|
|
29
|
+
read(maxSize: number): Promise<Buffer | null>;
|
|
30
|
+
/** Tell the peer to stop sending with the given error code. */
|
|
31
|
+
stop(code: number): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** A pending WebTransport session request from a client. */
|
|
35
|
+
export declare class NapiRequest {
|
|
36
|
+
/** Get the URL of the CONNECT request. */
|
|
37
|
+
get url(): Promise<string>;
|
|
38
|
+
/** Accept the session with 200 OK. */
|
|
39
|
+
ok(): Promise<NapiSession>;
|
|
40
|
+
/** Reject the session with the given HTTP status code. */
|
|
41
|
+
reject(status: number): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** A send stream for writing data. */
|
|
45
|
+
export declare class NapiSendStream {
|
|
46
|
+
/** Write data to the stream. */
|
|
47
|
+
write(data: Buffer): Promise<void>;
|
|
48
|
+
/** Signal that no more data will be written. */
|
|
49
|
+
finish(): Promise<void>;
|
|
50
|
+
/** Abruptly reset the stream with an error code. */
|
|
51
|
+
reset(code: number): Promise<void>;
|
|
52
|
+
/** Set the priority of the stream. */
|
|
53
|
+
setPriority(priority: number): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** A WebTransport server that accepts incoming sessions. */
|
|
57
|
+
export declare class NapiServer {
|
|
58
|
+
/** Create a server bound to the given address with the given TLS certificate. */
|
|
59
|
+
static bind(addr: string, certPem: Buffer, keyPem: Buffer): NapiServer;
|
|
60
|
+
/** Accept the next incoming WebTransport session request. */
|
|
61
|
+
accept(): Promise<NapiRequest | null>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** An established WebTransport session. */
|
|
65
|
+
export declare class NapiSession {
|
|
66
|
+
/** Accept an incoming unidirectional stream. */
|
|
67
|
+
acceptUni(): Promise<NapiRecvStream>;
|
|
68
|
+
/** Accept an incoming bidirectional stream. */
|
|
69
|
+
acceptBi(): Promise<NapiBiStream>;
|
|
70
|
+
/** Open a new unidirectional stream. */
|
|
71
|
+
openUni(): Promise<NapiSendStream>;
|
|
72
|
+
/** Open a new bidirectional stream. */
|
|
73
|
+
openBi(): Promise<NapiBiStream>;
|
|
74
|
+
/** Send a datagram. */
|
|
75
|
+
sendDatagram(data: Buffer): void;
|
|
76
|
+
/** Receive a datagram. */
|
|
77
|
+
recvDatagram(): Promise<Buffer>;
|
|
78
|
+
/** Get the maximum datagram size. */
|
|
79
|
+
maxDatagramSize(): number;
|
|
80
|
+
/** Close the session with a code and reason. */
|
|
81
|
+
close(code: number, reason: string): void;
|
|
82
|
+
/** Wait for the session to close, returning close info matching W3C WebTransportCloseInfo. */
|
|
83
|
+
closed(): Promise<NapiCloseInfo>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Info about why a session was closed, matching W3C WebTransportCloseInfo. */
|
|
87
|
+
export interface NapiCloseInfo {
|
|
88
|
+
closeCode: number;
|
|
89
|
+
reason: string;
|
|
90
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
// prettier-ignore
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
const { readFileSync } = require("node:fs");
|
|
7
|
+
let nativeBinding = null;
|
|
8
|
+
const loadErrors = [];
|
|
9
|
+
|
|
10
|
+
const isMusl = () => {
|
|
11
|
+
let musl = false;
|
|
12
|
+
if (process.platform === "linux") {
|
|
13
|
+
musl = isMuslFromFilesystem();
|
|
14
|
+
if (musl === null) {
|
|
15
|
+
musl = isMuslFromReport();
|
|
16
|
+
}
|
|
17
|
+
if (musl === null) {
|
|
18
|
+
musl = isMuslFromChildProcess();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return musl;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
|
|
25
|
+
|
|
26
|
+
const isMuslFromFilesystem = () => {
|
|
27
|
+
try {
|
|
28
|
+
return readFileSync("/usr/bin/ldd", "utf-8").includes("musl");
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const isMuslFromReport = () => {
|
|
35
|
+
let report = null;
|
|
36
|
+
if (typeof process.report?.getReport === "function") {
|
|
37
|
+
process.report.excludeNetwork = true;
|
|
38
|
+
report = process.report.getReport();
|
|
39
|
+
}
|
|
40
|
+
if (!report) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (report.header?.glibcVersionRuntime) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(report.sharedObjects)) {
|
|
47
|
+
if (report.sharedObjects.some(isFileMusl)) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const isMuslFromChildProcess = () => {
|
|
55
|
+
try {
|
|
56
|
+
return require("child_process").execSync("ldd --version", { encoding: "utf8" }).includes("musl");
|
|
57
|
+
} catch (_e) {
|
|
58
|
+
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
function requireNative() {
|
|
64
|
+
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
|
|
65
|
+
try {
|
|
66
|
+
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
loadErrors.push(err);
|
|
69
|
+
}
|
|
70
|
+
} else if (process.platform === "android") {
|
|
71
|
+
if (process.arch === "arm64") {
|
|
72
|
+
try {
|
|
73
|
+
return require("./web-transport.android-arm64.node");
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadErrors.push(e);
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const binding = require("@moq/web-transport-android-arm64");
|
|
79
|
+
const bindingPackageVersion = require("@moq/web-transport-android-arm64/package.json").version;
|
|
80
|
+
if (
|
|
81
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
82
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
83
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
84
|
+
) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
return binding;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
loadErrors.push(e);
|
|
92
|
+
}
|
|
93
|
+
} else if (process.arch === "arm") {
|
|
94
|
+
try {
|
|
95
|
+
return require("./web-transport.android-arm-eabi.node");
|
|
96
|
+
} catch (e) {
|
|
97
|
+
loadErrors.push(e);
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const binding = require("@moq/web-transport-android-arm-eabi");
|
|
101
|
+
const bindingPackageVersion = require("@moq/web-transport-android-arm-eabi/package.json").version;
|
|
102
|
+
if (
|
|
103
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
104
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
105
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
106
|
+
) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return binding;
|
|
112
|
+
} catch (e) {
|
|
113
|
+
loadErrors.push(e);
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
loadErrors.push(new Error(`Unsupported architecture on Android ${process.arch}`));
|
|
117
|
+
}
|
|
118
|
+
} else if (process.platform === "win32") {
|
|
119
|
+
if (process.arch === "x64") {
|
|
120
|
+
if (
|
|
121
|
+
process.config?.variables?.shlib_suffix === "dll.a" ||
|
|
122
|
+
process.config?.variables?.node_target_type === "shared_library"
|
|
123
|
+
) {
|
|
124
|
+
try {
|
|
125
|
+
return require("./web-transport.win32-x64-gnu.node");
|
|
126
|
+
} catch (e) {
|
|
127
|
+
loadErrors.push(e);
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
const binding = require("@moq/web-transport-win32-x64-gnu");
|
|
131
|
+
const bindingPackageVersion = require("@moq/web-transport-win32-x64-gnu/package.json").version;
|
|
132
|
+
if (
|
|
133
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
134
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
135
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
136
|
+
) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return binding;
|
|
142
|
+
} catch (e) {
|
|
143
|
+
loadErrors.push(e);
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
try {
|
|
147
|
+
return require("./web-transport.win32-x64-msvc.node");
|
|
148
|
+
} catch (e) {
|
|
149
|
+
loadErrors.push(e);
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const binding = require("@moq/web-transport-win32-x64-msvc");
|
|
153
|
+
const bindingPackageVersion = require("@moq/web-transport-win32-x64-msvc/package.json").version;
|
|
154
|
+
if (
|
|
155
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
156
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
157
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
158
|
+
) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return binding;
|
|
164
|
+
} catch (e) {
|
|
165
|
+
loadErrors.push(e);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} else if (process.arch === "ia32") {
|
|
169
|
+
try {
|
|
170
|
+
return require("./web-transport.win32-ia32-msvc.node");
|
|
171
|
+
} catch (e) {
|
|
172
|
+
loadErrors.push(e);
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const binding = require("@moq/web-transport-win32-ia32-msvc");
|
|
176
|
+
const bindingPackageVersion = require("@moq/web-transport-win32-ia32-msvc/package.json").version;
|
|
177
|
+
if (
|
|
178
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
179
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
180
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
181
|
+
) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
return binding;
|
|
187
|
+
} catch (e) {
|
|
188
|
+
loadErrors.push(e);
|
|
189
|
+
}
|
|
190
|
+
} else if (process.arch === "arm64") {
|
|
191
|
+
try {
|
|
192
|
+
return require("./web-transport.win32-arm64-msvc.node");
|
|
193
|
+
} catch (e) {
|
|
194
|
+
loadErrors.push(e);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const binding = require("@moq/web-transport-win32-arm64-msvc");
|
|
198
|
+
const bindingPackageVersion = require("@moq/web-transport-win32-arm64-msvc/package.json").version;
|
|
199
|
+
if (
|
|
200
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
201
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
202
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
203
|
+
) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return binding;
|
|
209
|
+
} catch (e) {
|
|
210
|
+
loadErrors.push(e);
|
|
211
|
+
}
|
|
212
|
+
} else {
|
|
213
|
+
loadErrors.push(new Error(`Unsupported architecture on Windows: ${process.arch}`));
|
|
214
|
+
}
|
|
215
|
+
} else if (process.platform === "darwin") {
|
|
216
|
+
try {
|
|
217
|
+
return require("./web-transport.darwin-universal.node");
|
|
218
|
+
} catch (e) {
|
|
219
|
+
loadErrors.push(e);
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const binding = require("@moq/web-transport-darwin-universal");
|
|
223
|
+
const bindingPackageVersion = require("@moq/web-transport-darwin-universal/package.json").version;
|
|
224
|
+
if (
|
|
225
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
226
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
227
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
228
|
+
) {
|
|
229
|
+
throw new Error(
|
|
230
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return binding;
|
|
234
|
+
} catch (e) {
|
|
235
|
+
loadErrors.push(e);
|
|
236
|
+
}
|
|
237
|
+
if (process.arch === "x64") {
|
|
238
|
+
try {
|
|
239
|
+
return require("./web-transport.darwin-x64.node");
|
|
240
|
+
} catch (e) {
|
|
241
|
+
loadErrors.push(e);
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const binding = require("@moq/web-transport-darwin-x64");
|
|
245
|
+
const bindingPackageVersion = require("@moq/web-transport-darwin-x64/package.json").version;
|
|
246
|
+
if (
|
|
247
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
248
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
249
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
250
|
+
) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
return binding;
|
|
256
|
+
} catch (e) {
|
|
257
|
+
loadErrors.push(e);
|
|
258
|
+
}
|
|
259
|
+
} else if (process.arch === "arm64") {
|
|
260
|
+
try {
|
|
261
|
+
return require("./web-transport.darwin-arm64.node");
|
|
262
|
+
} catch (e) {
|
|
263
|
+
loadErrors.push(e);
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const binding = require("@moq/web-transport-darwin-arm64");
|
|
267
|
+
const bindingPackageVersion = require("@moq/web-transport-darwin-arm64/package.json").version;
|
|
268
|
+
if (
|
|
269
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
270
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
271
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
272
|
+
) {
|
|
273
|
+
throw new Error(
|
|
274
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
return binding;
|
|
278
|
+
} catch (e) {
|
|
279
|
+
loadErrors.push(e);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
loadErrors.push(new Error(`Unsupported architecture on macOS: ${process.arch}`));
|
|
283
|
+
}
|
|
284
|
+
} else if (process.platform === "freebsd") {
|
|
285
|
+
if (process.arch === "x64") {
|
|
286
|
+
try {
|
|
287
|
+
return require("./web-transport.freebsd-x64.node");
|
|
288
|
+
} catch (e) {
|
|
289
|
+
loadErrors.push(e);
|
|
290
|
+
}
|
|
291
|
+
try {
|
|
292
|
+
const binding = require("@moq/web-transport-freebsd-x64");
|
|
293
|
+
const bindingPackageVersion = require("@moq/web-transport-freebsd-x64/package.json").version;
|
|
294
|
+
if (
|
|
295
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
296
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
297
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
298
|
+
) {
|
|
299
|
+
throw new Error(
|
|
300
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
return binding;
|
|
304
|
+
} catch (e) {
|
|
305
|
+
loadErrors.push(e);
|
|
306
|
+
}
|
|
307
|
+
} else if (process.arch === "arm64") {
|
|
308
|
+
try {
|
|
309
|
+
return require("./web-transport.freebsd-arm64.node");
|
|
310
|
+
} catch (e) {
|
|
311
|
+
loadErrors.push(e);
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
const binding = require("@moq/web-transport-freebsd-arm64");
|
|
315
|
+
const bindingPackageVersion = require("@moq/web-transport-freebsd-arm64/package.json").version;
|
|
316
|
+
if (
|
|
317
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
318
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
319
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
320
|
+
) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
return binding;
|
|
326
|
+
} catch (e) {
|
|
327
|
+
loadErrors.push(e);
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
loadErrors.push(new Error(`Unsupported architecture on FreeBSD: ${process.arch}`));
|
|
331
|
+
}
|
|
332
|
+
} else if (process.platform === "linux") {
|
|
333
|
+
if (process.arch === "x64") {
|
|
334
|
+
if (isMusl()) {
|
|
335
|
+
try {
|
|
336
|
+
return require("./web-transport.linux-x64-musl.node");
|
|
337
|
+
} catch (e) {
|
|
338
|
+
loadErrors.push(e);
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
const binding = require("@moq/web-transport-linux-x64-musl");
|
|
342
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-x64-musl/package.json").version;
|
|
343
|
+
if (
|
|
344
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
345
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
346
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
347
|
+
) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return binding;
|
|
353
|
+
} catch (e) {
|
|
354
|
+
loadErrors.push(e);
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
try {
|
|
358
|
+
return require("./web-transport.linux-x64-gnu.node");
|
|
359
|
+
} catch (e) {
|
|
360
|
+
loadErrors.push(e);
|
|
361
|
+
}
|
|
362
|
+
try {
|
|
363
|
+
const binding = require("@moq/web-transport-linux-x64-gnu");
|
|
364
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-x64-gnu/package.json").version;
|
|
365
|
+
if (
|
|
366
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
367
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
368
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
369
|
+
) {
|
|
370
|
+
throw new Error(
|
|
371
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
return binding;
|
|
375
|
+
} catch (e) {
|
|
376
|
+
loadErrors.push(e);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
} else if (process.arch === "arm64") {
|
|
380
|
+
if (isMusl()) {
|
|
381
|
+
try {
|
|
382
|
+
return require("./web-transport.linux-arm64-musl.node");
|
|
383
|
+
} catch (e) {
|
|
384
|
+
loadErrors.push(e);
|
|
385
|
+
}
|
|
386
|
+
try {
|
|
387
|
+
const binding = require("@moq/web-transport-linux-arm64-musl");
|
|
388
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-arm64-musl/package.json").version;
|
|
389
|
+
if (
|
|
390
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
391
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
392
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
393
|
+
) {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
return binding;
|
|
399
|
+
} catch (e) {
|
|
400
|
+
loadErrors.push(e);
|
|
401
|
+
}
|
|
402
|
+
} else {
|
|
403
|
+
try {
|
|
404
|
+
return require("./web-transport.linux-arm64-gnu.node");
|
|
405
|
+
} catch (e) {
|
|
406
|
+
loadErrors.push(e);
|
|
407
|
+
}
|
|
408
|
+
try {
|
|
409
|
+
const binding = require("@moq/web-transport-linux-arm64-gnu");
|
|
410
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-arm64-gnu/package.json").version;
|
|
411
|
+
if (
|
|
412
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
413
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
414
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
415
|
+
) {
|
|
416
|
+
throw new Error(
|
|
417
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
return binding;
|
|
421
|
+
} catch (e) {
|
|
422
|
+
loadErrors.push(e);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
} else if (process.arch === "arm") {
|
|
426
|
+
if (isMusl()) {
|
|
427
|
+
try {
|
|
428
|
+
return require("./web-transport.linux-arm-musleabihf.node");
|
|
429
|
+
} catch (e) {
|
|
430
|
+
loadErrors.push(e);
|
|
431
|
+
}
|
|
432
|
+
try {
|
|
433
|
+
const binding = require("@moq/web-transport-linux-arm-musleabihf");
|
|
434
|
+
const bindingPackageVersion =
|
|
435
|
+
require("@moq/web-transport-linux-arm-musleabihf/package.json").version;
|
|
436
|
+
if (
|
|
437
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
438
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
439
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
440
|
+
) {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
return binding;
|
|
446
|
+
} catch (e) {
|
|
447
|
+
loadErrors.push(e);
|
|
448
|
+
}
|
|
449
|
+
} else {
|
|
450
|
+
try {
|
|
451
|
+
return require("./web-transport.linux-arm-gnueabihf.node");
|
|
452
|
+
} catch (e) {
|
|
453
|
+
loadErrors.push(e);
|
|
454
|
+
}
|
|
455
|
+
try {
|
|
456
|
+
const binding = require("@moq/web-transport-linux-arm-gnueabihf");
|
|
457
|
+
const bindingPackageVersion =
|
|
458
|
+
require("@moq/web-transport-linux-arm-gnueabihf/package.json").version;
|
|
459
|
+
if (
|
|
460
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
461
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
462
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
463
|
+
) {
|
|
464
|
+
throw new Error(
|
|
465
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
return binding;
|
|
469
|
+
} catch (e) {
|
|
470
|
+
loadErrors.push(e);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
} else if (process.arch === "loong64") {
|
|
474
|
+
if (isMusl()) {
|
|
475
|
+
try {
|
|
476
|
+
return require("./web-transport.linux-loong64-musl.node");
|
|
477
|
+
} catch (e) {
|
|
478
|
+
loadErrors.push(e);
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
const binding = require("@moq/web-transport-linux-loong64-musl");
|
|
482
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-loong64-musl/package.json").version;
|
|
483
|
+
if (
|
|
484
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
485
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
486
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
487
|
+
) {
|
|
488
|
+
throw new Error(
|
|
489
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
return binding;
|
|
493
|
+
} catch (e) {
|
|
494
|
+
loadErrors.push(e);
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
try {
|
|
498
|
+
return require("./web-transport.linux-loong64-gnu.node");
|
|
499
|
+
} catch (e) {
|
|
500
|
+
loadErrors.push(e);
|
|
501
|
+
}
|
|
502
|
+
try {
|
|
503
|
+
const binding = require("@moq/web-transport-linux-loong64-gnu");
|
|
504
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-loong64-gnu/package.json").version;
|
|
505
|
+
if (
|
|
506
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
507
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
508
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
509
|
+
) {
|
|
510
|
+
throw new Error(
|
|
511
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
return binding;
|
|
515
|
+
} catch (e) {
|
|
516
|
+
loadErrors.push(e);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
} else if (process.arch === "riscv64") {
|
|
520
|
+
if (isMusl()) {
|
|
521
|
+
try {
|
|
522
|
+
return require("./web-transport.linux-riscv64-musl.node");
|
|
523
|
+
} catch (e) {
|
|
524
|
+
loadErrors.push(e);
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
const binding = require("@moq/web-transport-linux-riscv64-musl");
|
|
528
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-riscv64-musl/package.json").version;
|
|
529
|
+
if (
|
|
530
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
531
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
532
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
533
|
+
) {
|
|
534
|
+
throw new Error(
|
|
535
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
return binding;
|
|
539
|
+
} catch (e) {
|
|
540
|
+
loadErrors.push(e);
|
|
541
|
+
}
|
|
542
|
+
} else {
|
|
543
|
+
try {
|
|
544
|
+
return require("./web-transport.linux-riscv64-gnu.node");
|
|
545
|
+
} catch (e) {
|
|
546
|
+
loadErrors.push(e);
|
|
547
|
+
}
|
|
548
|
+
try {
|
|
549
|
+
const binding = require("@moq/web-transport-linux-riscv64-gnu");
|
|
550
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-riscv64-gnu/package.json").version;
|
|
551
|
+
if (
|
|
552
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
553
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
554
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
555
|
+
) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
return binding;
|
|
561
|
+
} catch (e) {
|
|
562
|
+
loadErrors.push(e);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
} else if (process.arch === "ppc64") {
|
|
566
|
+
try {
|
|
567
|
+
return require("./web-transport.linux-ppc64-gnu.node");
|
|
568
|
+
} catch (e) {
|
|
569
|
+
loadErrors.push(e);
|
|
570
|
+
}
|
|
571
|
+
try {
|
|
572
|
+
const binding = require("@moq/web-transport-linux-ppc64-gnu");
|
|
573
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-ppc64-gnu/package.json").version;
|
|
574
|
+
if (
|
|
575
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
576
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
577
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
578
|
+
) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
return binding;
|
|
584
|
+
} catch (e) {
|
|
585
|
+
loadErrors.push(e);
|
|
586
|
+
}
|
|
587
|
+
} else if (process.arch === "s390x") {
|
|
588
|
+
try {
|
|
589
|
+
return require("./web-transport.linux-s390x-gnu.node");
|
|
590
|
+
} catch (e) {
|
|
591
|
+
loadErrors.push(e);
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
const binding = require("@moq/web-transport-linux-s390x-gnu");
|
|
595
|
+
const bindingPackageVersion = require("@moq/web-transport-linux-s390x-gnu/package.json").version;
|
|
596
|
+
if (
|
|
597
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
598
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
599
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
600
|
+
) {
|
|
601
|
+
throw new Error(
|
|
602
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
return binding;
|
|
606
|
+
} catch (e) {
|
|
607
|
+
loadErrors.push(e);
|
|
608
|
+
}
|
|
609
|
+
} else {
|
|
610
|
+
loadErrors.push(new Error(`Unsupported architecture on Linux: ${process.arch}`));
|
|
611
|
+
}
|
|
612
|
+
} else if (process.platform === "openharmony") {
|
|
613
|
+
if (process.arch === "arm64") {
|
|
614
|
+
try {
|
|
615
|
+
return require("./web-transport.openharmony-arm64.node");
|
|
616
|
+
} catch (e) {
|
|
617
|
+
loadErrors.push(e);
|
|
618
|
+
}
|
|
619
|
+
try {
|
|
620
|
+
const binding = require("@moq/web-transport-openharmony-arm64");
|
|
621
|
+
const bindingPackageVersion = require("@moq/web-transport-openharmony-arm64/package.json").version;
|
|
622
|
+
if (
|
|
623
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
624
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
625
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
626
|
+
) {
|
|
627
|
+
throw new Error(
|
|
628
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
return binding;
|
|
632
|
+
} catch (e) {
|
|
633
|
+
loadErrors.push(e);
|
|
634
|
+
}
|
|
635
|
+
} else if (process.arch === "x64") {
|
|
636
|
+
try {
|
|
637
|
+
return require("./web-transport.openharmony-x64.node");
|
|
638
|
+
} catch (e) {
|
|
639
|
+
loadErrors.push(e);
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
const binding = require("@moq/web-transport-openharmony-x64");
|
|
643
|
+
const bindingPackageVersion = require("@moq/web-transport-openharmony-x64/package.json").version;
|
|
644
|
+
if (
|
|
645
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
646
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
647
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
648
|
+
) {
|
|
649
|
+
throw new Error(
|
|
650
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
651
|
+
);
|
|
652
|
+
}
|
|
653
|
+
return binding;
|
|
654
|
+
} catch (e) {
|
|
655
|
+
loadErrors.push(e);
|
|
656
|
+
}
|
|
657
|
+
} else if (process.arch === "arm") {
|
|
658
|
+
try {
|
|
659
|
+
return require("./web-transport.openharmony-arm.node");
|
|
660
|
+
} catch (e) {
|
|
661
|
+
loadErrors.push(e);
|
|
662
|
+
}
|
|
663
|
+
try {
|
|
664
|
+
const binding = require("@moq/web-transport-openharmony-arm");
|
|
665
|
+
const bindingPackageVersion = require("@moq/web-transport-openharmony-arm/package.json").version;
|
|
666
|
+
if (
|
|
667
|
+
bindingPackageVersion !== "0.0.1" &&
|
|
668
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
669
|
+
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0"
|
|
670
|
+
) {
|
|
671
|
+
throw new Error(
|
|
672
|
+
`Native binding package version mismatch, expected 0.0.1 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
return binding;
|
|
676
|
+
} catch (e) {
|
|
677
|
+
loadErrors.push(e);
|
|
678
|
+
}
|
|
679
|
+
} else {
|
|
680
|
+
loadErrors.push(new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`));
|
|
681
|
+
}
|
|
682
|
+
} else {
|
|
683
|
+
loadErrors.push(new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`));
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
nativeBinding = requireNative();
|
|
688
|
+
|
|
689
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
690
|
+
let wasiBinding = null;
|
|
691
|
+
let wasiBindingError = null;
|
|
692
|
+
try {
|
|
693
|
+
wasiBinding = require("./web-transport.wasi.cjs");
|
|
694
|
+
nativeBinding = wasiBinding;
|
|
695
|
+
} catch (err) {
|
|
696
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
697
|
+
wasiBindingError = err;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
701
|
+
try {
|
|
702
|
+
wasiBinding = require("@moq/web-transport-wasm32-wasi");
|
|
703
|
+
nativeBinding = wasiBinding;
|
|
704
|
+
} catch (err) {
|
|
705
|
+
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
706
|
+
if (!wasiBindingError) {
|
|
707
|
+
wasiBindingError = err;
|
|
708
|
+
} else {
|
|
709
|
+
wasiBindingError.cause = err;
|
|
710
|
+
}
|
|
711
|
+
loadErrors.push(err);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
if (process.env.NAPI_RS_FORCE_WASI === "error" && !wasiBinding) {
|
|
716
|
+
const error = new Error("WASI binding not found and NAPI_RS_FORCE_WASI is set to error");
|
|
717
|
+
error.cause = wasiBindingError;
|
|
718
|
+
throw error;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (!nativeBinding) {
|
|
723
|
+
if (loadErrors.length > 0) {
|
|
724
|
+
throw new Error(
|
|
725
|
+
`Cannot find native binding. ` +
|
|
726
|
+
`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). ` +
|
|
727
|
+
"Please try `npm i` again after removing both package-lock.json and node_modules directory.",
|
|
728
|
+
{
|
|
729
|
+
cause: loadErrors.reduce((err, cur) => {
|
|
730
|
+
cur.cause = err;
|
|
731
|
+
return cur;
|
|
732
|
+
}),
|
|
733
|
+
},
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
throw new Error(`Failed to load native binding`);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
module.exports = nativeBinding;
|
|
740
|
+
module.exports.NapiBiStream = nativeBinding.NapiBiStream;
|
|
741
|
+
module.exports.NapiClient = nativeBinding.NapiClient;
|
|
742
|
+
module.exports.NapiRecvStream = nativeBinding.NapiRecvStream;
|
|
743
|
+
module.exports.NapiRequest = nativeBinding.NapiRequest;
|
|
744
|
+
module.exports.NapiSendStream = nativeBinding.NapiSendStream;
|
|
745
|
+
module.exports.NapiServer = nativeBinding.NapiServer;
|
|
746
|
+
module.exports.NapiSession = nativeBinding.NapiSession;
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moq/web-transport",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "WebTransport polyfill for Node.js via QUIC/HTTP3",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "(MIT OR Apache-2.0)",
|
|
7
|
+
"repository": "github:moq-dev/web-transport",
|
|
8
|
+
"napi": {
|
|
9
|
+
"binaryName": "web-transport",
|
|
10
|
+
"targets": [
|
|
11
|
+
"x86_64-apple-darwin",
|
|
12
|
+
"aarch64-apple-darwin",
|
|
13
|
+
"x86_64-pc-windows-msvc",
|
|
14
|
+
"x86_64-unknown-linux-gnu",
|
|
15
|
+
"aarch64-unknown-linux-gnu"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
".": "./src/index.ts"
|
|
20
|
+
},
|
|
21
|
+
"types": "./src/index.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"./src",
|
|
24
|
+
"index.js",
|
|
25
|
+
"index.d.ts",
|
|
26
|
+
"*.node"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "napi build --platform --release --manifest-path ../../rs/web-transport-node/Cargo.toml --output-dir .",
|
|
30
|
+
"check": "tsc --noEmit",
|
|
31
|
+
"release": "bun scripts/release.ts"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@napi-rs/cli": "^3",
|
|
35
|
+
"typescript": "^5.9.2",
|
|
36
|
+
"@types/node": "^24.3.0"
|
|
37
|
+
},
|
|
38
|
+
"optionalDependencies": {
|
|
39
|
+
"@moq/web-transport-darwin-x64": "0.0.1",
|
|
40
|
+
"@moq/web-transport-darwin-arm64": "0.0.1",
|
|
41
|
+
"@moq/web-transport-win32-x64-msvc": "0.0.1",
|
|
42
|
+
"@moq/web-transport-linux-x64-gnu": "0.0.1",
|
|
43
|
+
"@moq/web-transport-linux-arm64-gnu": "0.0.1"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"webtransport",
|
|
47
|
+
"quic",
|
|
48
|
+
"http3",
|
|
49
|
+
"polyfill",
|
|
50
|
+
"napi"
|
|
51
|
+
]
|
|
52
|
+
}
|
package/src/datagrams.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { NapiSession } from "../index.js";
|
|
2
|
+
|
|
3
|
+
export class Datagrams implements WebTransportDatagramDuplexStream {
|
|
4
|
+
readonly readable: ReadableStream<Uint8Array>;
|
|
5
|
+
readonly writable: WritableStream<Uint8Array>;
|
|
6
|
+
|
|
7
|
+
// Required by the interface but not meaningfully configurable here.
|
|
8
|
+
incomingHighWaterMark = 1;
|
|
9
|
+
incomingMaxAge: number | null = null;
|
|
10
|
+
outgoingHighWaterMark = 1;
|
|
11
|
+
outgoingMaxAge: number | null = null;
|
|
12
|
+
|
|
13
|
+
#session: NapiSession;
|
|
14
|
+
|
|
15
|
+
constructor(session: NapiSession) {
|
|
16
|
+
this.#session = session;
|
|
17
|
+
|
|
18
|
+
this.readable = new ReadableStream({
|
|
19
|
+
async pull(controller) {
|
|
20
|
+
try {
|
|
21
|
+
const data = await session.recvDatagram();
|
|
22
|
+
controller.enqueue(new Uint8Array(data));
|
|
23
|
+
} catch {
|
|
24
|
+
controller.close();
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.writable = new WritableStream({
|
|
30
|
+
write(chunk) {
|
|
31
|
+
session.sendDatagram(Buffer.from(chunk));
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get maxDatagramSize(): number {
|
|
37
|
+
return this.#session.maxDatagramSize();
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Session from "./session.ts";
|
|
2
|
+
|
|
3
|
+
// Install polyfill if WebTransport is not available, returning true if installed
|
|
4
|
+
export function install(): boolean {
|
|
5
|
+
if ("WebTransport" in globalThis) return false;
|
|
6
|
+
// biome-ignore lint/suspicious/noExplicitAny: polyfill
|
|
7
|
+
(globalThis as any).WebTransport = Session;
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default Session;
|
|
12
|
+
export { NapiRequest, NapiServer } from "../index.js";
|
package/src/session.ts
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { NapiClient, type NapiRecvStream, type NapiSendStream, type NapiSession } from "../index.js";
|
|
2
|
+
import { Datagrams } from "./datagrams.ts";
|
|
3
|
+
|
|
4
|
+
function wrapRecvStream(recv: NapiRecvStream): ReadableStream<Uint8Array> {
|
|
5
|
+
return new ReadableStream({
|
|
6
|
+
async pull(controller) {
|
|
7
|
+
const chunk = await recv.read(65536);
|
|
8
|
+
if (chunk) {
|
|
9
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
10
|
+
} else {
|
|
11
|
+
controller.close();
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
cancel() {
|
|
15
|
+
recv.stop(0).catch(() => {});
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function wrapSendStream(send: NapiSendStream): WritableStream<Uint8Array> {
|
|
21
|
+
return new WritableStream({
|
|
22
|
+
async write(chunk) {
|
|
23
|
+
await send.write(Buffer.from(chunk));
|
|
24
|
+
},
|
|
25
|
+
async close() {
|
|
26
|
+
await send.finish();
|
|
27
|
+
},
|
|
28
|
+
async abort() {
|
|
29
|
+
await send.reset(0);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SessionOptions extends WebTransportOptions {
|
|
35
|
+
/** Skip all certificate verification. Only use for testing. */
|
|
36
|
+
serverCertificateDisableVerify?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default class Session implements WebTransport {
|
|
40
|
+
readonly ready: Promise<void>;
|
|
41
|
+
readonly closed: Promise<WebTransportCloseInfo>;
|
|
42
|
+
readonly datagrams: WebTransportDatagramDuplexStream;
|
|
43
|
+
|
|
44
|
+
#session: NapiSession | undefined;
|
|
45
|
+
#pendingClose: { closeCode: number; reason: string } | undefined;
|
|
46
|
+
#incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalStream> | undefined;
|
|
47
|
+
#incomingUnidirectionalStreams: ReadableStream<ReadableStream<Uint8Array>> | undefined;
|
|
48
|
+
|
|
49
|
+
// Construct from URL (client-side polyfill)
|
|
50
|
+
constructor(url: string | URL, options?: SessionOptions);
|
|
51
|
+
// Construct from existing NapiSession (server-side)
|
|
52
|
+
constructor(session: NapiSession);
|
|
53
|
+
constructor(urlOrSession: string | URL | NapiSession, options?: SessionOptions) {
|
|
54
|
+
const ready = Promise.withResolvers<void>();
|
|
55
|
+
const closed = Promise.withResolvers<WebTransportCloseInfo>();
|
|
56
|
+
this.ready = ready.promise;
|
|
57
|
+
this.closed = closed.promise;
|
|
58
|
+
|
|
59
|
+
// Check if we got an existing NapiSession (server-side path)
|
|
60
|
+
if (typeof urlOrSession === "object" && !(urlOrSession instanceof URL)) {
|
|
61
|
+
this.#session = urlOrSession;
|
|
62
|
+
this.datagrams = new Datagrams(urlOrSession);
|
|
63
|
+
|
|
64
|
+
ready.resolve();
|
|
65
|
+
|
|
66
|
+
urlOrSession.closed().then((info) => {
|
|
67
|
+
closed.resolve({ closeCode: info.closeCode, reason: info.reason });
|
|
68
|
+
});
|
|
69
|
+
} else {
|
|
70
|
+
// Client-side: create NapiClient and connect
|
|
71
|
+
const url = typeof urlOrSession === "string" ? urlOrSession : urlOrSession.toString();
|
|
72
|
+
|
|
73
|
+
// Provide a deferred Datagrams that works before connect resolves.
|
|
74
|
+
// The real session will be bound once connect succeeds.
|
|
75
|
+
this.datagrams = new DeferredDatagrams();
|
|
76
|
+
|
|
77
|
+
const hashes = options?.serverCertificateHashes;
|
|
78
|
+
if (options?.serverCertificateDisableVerify && hashes && hashes.length > 0) {
|
|
79
|
+
throw new Error("serverCertificateDisableVerify and serverCertificateHashes cannot be used together");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let client: NapiClient;
|
|
83
|
+
if (options?.serverCertificateDisableVerify) {
|
|
84
|
+
client = NapiClient.disableVerify();
|
|
85
|
+
} else if (hashes && hashes.length > 0) {
|
|
86
|
+
const buffers = hashes
|
|
87
|
+
.filter((h): h is WebTransportHash & { value: BufferSource } => h.value != null)
|
|
88
|
+
.map((h) => Buffer.from(h.value as ArrayBuffer));
|
|
89
|
+
client = NapiClient.withCertificateHashes(buffers);
|
|
90
|
+
} else {
|
|
91
|
+
client = NapiClient.withSystemRoots();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
client
|
|
95
|
+
.connect(url)
|
|
96
|
+
.then((session) => {
|
|
97
|
+
// Check if close() was called before connect completed.
|
|
98
|
+
if (this.#pendingClose) {
|
|
99
|
+
session.close(this.#pendingClose.closeCode, this.#pendingClose.reason);
|
|
100
|
+
(this.datagrams as DeferredDatagrams).fail(new Error("session closed before connect"));
|
|
101
|
+
closed.resolve(this.#pendingClose);
|
|
102
|
+
ready.reject(new Error("session closed before connect"));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.#session = session;
|
|
107
|
+
(this.datagrams as DeferredDatagrams).bind(session);
|
|
108
|
+
ready.resolve();
|
|
109
|
+
|
|
110
|
+
session.closed().then((info) => {
|
|
111
|
+
closed.resolve({ closeCode: info.closeCode, reason: info.reason });
|
|
112
|
+
});
|
|
113
|
+
})
|
|
114
|
+
.catch((err) => {
|
|
115
|
+
(this.datagrams as DeferredDatagrams).fail(err instanceof Error ? err : new Error(String(err)));
|
|
116
|
+
ready.reject(err instanceof Error ? err : new Error(String(err)));
|
|
117
|
+
closed.resolve({ closeCode: 0, reason: String(err) });
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
get incomingBidirectionalStreams(): ReadableStream<WebTransportBidirectionalStream> {
|
|
123
|
+
if (!this.#incomingBidirectionalStreams) {
|
|
124
|
+
this.#incomingBidirectionalStreams = new ReadableStream({
|
|
125
|
+
pull: async (controller) => {
|
|
126
|
+
await this.ready;
|
|
127
|
+
const session = this.#session;
|
|
128
|
+
if (!session) {
|
|
129
|
+
controller.close();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const bi = await session.acceptBi();
|
|
134
|
+
const stream: WebTransportBidirectionalStream = {
|
|
135
|
+
readable: wrapRecvStream(bi.takeRecv()),
|
|
136
|
+
writable: wrapSendStream(bi.takeSend()),
|
|
137
|
+
};
|
|
138
|
+
controller.enqueue(stream);
|
|
139
|
+
} catch {
|
|
140
|
+
controller.close();
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return this.#incomingBidirectionalStreams;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
get incomingUnidirectionalStreams(): ReadableStream<ReadableStream<Uint8Array>> {
|
|
149
|
+
if (!this.#incomingUnidirectionalStreams) {
|
|
150
|
+
this.#incomingUnidirectionalStreams = new ReadableStream({
|
|
151
|
+
pull: async (controller) => {
|
|
152
|
+
await this.ready;
|
|
153
|
+
const session = this.#session;
|
|
154
|
+
if (!session) {
|
|
155
|
+
controller.close();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const recv = await session.acceptUni();
|
|
160
|
+
controller.enqueue(wrapRecvStream(recv));
|
|
161
|
+
} catch {
|
|
162
|
+
controller.close();
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return this.#incomingUnidirectionalStreams;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async createBidirectionalStream(): Promise<WebTransportBidirectionalStream> {
|
|
171
|
+
await this.ready;
|
|
172
|
+
if (!this.#session) throw new Error("session not connected");
|
|
173
|
+
const bi = await this.#session.openBi();
|
|
174
|
+
return {
|
|
175
|
+
readable: wrapRecvStream(bi.takeRecv()),
|
|
176
|
+
writable: wrapSendStream(bi.takeSend()),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async createUnidirectionalStream(): Promise<WritableStream<Uint8Array>> {
|
|
181
|
+
await this.ready;
|
|
182
|
+
if (!this.#session) throw new Error("session not connected");
|
|
183
|
+
const send = await this.#session.openUni();
|
|
184
|
+
return wrapSendStream(send);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
close(info?: { closeCode?: number; reason?: string }): void {
|
|
188
|
+
const closeCode = info?.closeCode ?? 0;
|
|
189
|
+
const reason = info?.reason ?? "";
|
|
190
|
+
if (this.#session) {
|
|
191
|
+
this.#session.close(closeCode, reason);
|
|
192
|
+
} else {
|
|
193
|
+
// Connect hasn't completed yet — flag for when it does.
|
|
194
|
+
this.#pendingClose = { closeCode, reason };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
get congestionControl(): WebTransportCongestionControl {
|
|
199
|
+
return "default";
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* A WebTransportDatagramDuplexStream that works before the session is connected.
|
|
205
|
+
* Readable/writable block until bind() is called with the real session.
|
|
206
|
+
*/
|
|
207
|
+
class DeferredDatagrams implements WebTransportDatagramDuplexStream {
|
|
208
|
+
readonly readable: ReadableStream<Uint8Array>;
|
|
209
|
+
readonly writable: WritableStream<Uint8Array>;
|
|
210
|
+
|
|
211
|
+
incomingHighWaterMark = 1;
|
|
212
|
+
incomingMaxAge: number | null = null;
|
|
213
|
+
outgoingHighWaterMark = 1;
|
|
214
|
+
outgoingMaxAge: number | null = null;
|
|
215
|
+
|
|
216
|
+
#session: NapiSession | undefined;
|
|
217
|
+
#bound = Promise.withResolvers<void>();
|
|
218
|
+
|
|
219
|
+
constructor() {
|
|
220
|
+
this.readable = new ReadableStream({
|
|
221
|
+
pull: async (controller) => {
|
|
222
|
+
// Wait for session to be bound
|
|
223
|
+
if (!this.#session) {
|
|
224
|
+
try {
|
|
225
|
+
await this.#bound.promise;
|
|
226
|
+
} catch {
|
|
227
|
+
controller.close();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!this.#session) {
|
|
232
|
+
controller.close();
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const data = await this.#session.recvDatagram();
|
|
237
|
+
controller.enqueue(new Uint8Array(data));
|
|
238
|
+
} catch {
|
|
239
|
+
controller.close();
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
this.writable = new WritableStream({
|
|
245
|
+
write: (chunk) => {
|
|
246
|
+
if (!this.#session) throw new Error("session not connected");
|
|
247
|
+
this.#session.sendDatagram(Buffer.from(chunk));
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
bind(session: NapiSession) {
|
|
253
|
+
this.#session = session;
|
|
254
|
+
this.#bound.resolve();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
fail(_error: Error) {
|
|
258
|
+
this.#bound.reject(_error);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
get maxDatagramSize(): number {
|
|
262
|
+
return this.#session?.maxDatagramSize() ?? 0;
|
|
263
|
+
}
|
|
264
|
+
}
|