@ldtr/nestjs-webtransport 0.0.2 → 0.0.4
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/dist/index.cjs +83 -46
- package/package.json +5 -3
- package/dist/index.d.mts +0 -87
- package/dist/index.mjs +0 -423
package/dist/index.cjs
CHANGED
|
@@ -50,6 +50,10 @@ async function* generateUStream(session) {
|
|
|
50
50
|
reader.releaseLock();
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
function isSessionClosedNormally(error) {
|
|
54
|
+
if (!(error instanceof Error)) return false;
|
|
55
|
+
return error.name === "WebTransportError" && /session closed/i.test(error.message) && /code 0/i.test(error.message);
|
|
56
|
+
}
|
|
53
57
|
async function* generateChunks(reader) {
|
|
54
58
|
try {
|
|
55
59
|
while (true) {
|
|
@@ -57,6 +61,8 @@ async function* generateChunks(reader) {
|
|
|
57
61
|
if (done) break;
|
|
58
62
|
yield value;
|
|
59
63
|
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (!isSessionClosedNormally(error)) throw error;
|
|
60
66
|
} finally {
|
|
61
67
|
reader.releaseLock();
|
|
62
68
|
}
|
|
@@ -170,8 +176,21 @@ var WtStreamWO = class extends AbstractWtStream {
|
|
|
170
176
|
}
|
|
171
177
|
};
|
|
172
178
|
//#endregion
|
|
179
|
+
//#region \0@oxc-project+runtime@0.135.0/helpers/esm/decorateMetadata.js
|
|
180
|
+
function __decorateMetadata(k, v) {
|
|
181
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
//#region \0@oxc-project+runtime@0.135.0/helpers/esm/decorate.js
|
|
185
|
+
function __decorate(decorators, target, key, desc) {
|
|
186
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
187
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
188
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
189
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
173
192
|
//#region src/lib/explorers/webtransport-gateway.explorer.ts
|
|
174
|
-
|
|
193
|
+
let WebTransportGatewayExplorer = class WebTransportGatewayExplorer {
|
|
175
194
|
discoveryService;
|
|
176
195
|
constructor(discoveryService) {
|
|
177
196
|
this.discoveryService = discoveryService;
|
|
@@ -196,9 +215,10 @@ var WebTransportGatewayExplorer = @((0, _nestjs_common.Injectable)()) class {
|
|
|
196
215
|
return gatewaysByNameByPath;
|
|
197
216
|
}
|
|
198
217
|
};
|
|
218
|
+
WebTransportGatewayExplorer = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof _nestjs_core.DiscoveryService === "undefined" ? Object : _nestjs_core.DiscoveryService])], WebTransportGatewayExplorer);
|
|
199
219
|
//#endregion
|
|
200
220
|
//#region src/lib/explorers/webtransport-server.explorer.ts
|
|
201
|
-
|
|
221
|
+
let WebTransportServerExplorer = class WebTransportServerExplorer {
|
|
202
222
|
discoveryService;
|
|
203
223
|
constructor(discoveryService) {
|
|
204
224
|
this.discoveryService = discoveryService;
|
|
@@ -217,45 +237,14 @@ var WebTransportServerExplorer = @((0, _nestjs_common.Injectable)()) class {
|
|
|
217
237
|
return serversByName;
|
|
218
238
|
}
|
|
219
239
|
};
|
|
220
|
-
|
|
221
|
-
//#region src/lib/bootstraps/web-transport-bootstrapper.ts
|
|
222
|
-
var WebTransportBootstrapper = @((0, _nestjs_common.Injectable)()) class WebTransportBootstrapper {
|
|
223
|
-
serverFactory;
|
|
224
|
-
webTransportExplorer;
|
|
225
|
-
logger = new _nestjs_common.Logger(WebTransportBootstrapper.name);
|
|
226
|
-
h3ServersWithInfo = [];
|
|
227
|
-
constructor(serverFactory, webTransportExplorer) {
|
|
228
|
-
this.serverFactory = serverFactory;
|
|
229
|
-
this.webTransportExplorer = webTransportExplorer;
|
|
230
|
-
}
|
|
231
|
-
async onApplicationBootstrap() {
|
|
232
|
-
const serverBindings = this.webTransportExplorer.discover();
|
|
233
|
-
this.h3ServersWithInfo = await this.serverFactory.createH3Servers(serverBindings);
|
|
234
|
-
await Promise.all(this.h3ServersWithInfo.map(async ({ options, name, h3Server }) => {
|
|
235
|
-
try {
|
|
236
|
-
h3Server.startServer();
|
|
237
|
-
await h3Server.ready;
|
|
238
|
-
this.logger.log(`WebTransport server "${name}" is ready on ${options.host}:${options.port}`);
|
|
239
|
-
} catch (e) {
|
|
240
|
-
this.logger.error(`Failed to start WebTransport server "${name}" on ${options.host}:${options.port}`);
|
|
241
|
-
throw e;
|
|
242
|
-
}
|
|
243
|
-
}));
|
|
244
|
-
}
|
|
245
|
-
async onApplicationShutdown() {
|
|
246
|
-
await Promise.all(this.h3ServersWithInfo.map(async ({ name, h3Server }) => {
|
|
247
|
-
h3Server.stopServer();
|
|
248
|
-
await h3Server.closed;
|
|
249
|
-
this.logger.log(`WebTransport server "${name}" stopped`);
|
|
250
|
-
}));
|
|
251
|
-
}
|
|
252
|
-
};
|
|
240
|
+
WebTransportServerExplorer = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof _nestjs_core.DiscoveryService === "undefined" ? Object : _nestjs_core.DiscoveryService])], WebTransportServerExplorer);
|
|
253
241
|
//#endregion
|
|
254
242
|
//#region src/lib/explorers/web-transport.explorer.ts
|
|
255
|
-
var
|
|
243
|
+
var _WebTransportExplorer;
|
|
244
|
+
let WebTransportExplorer = _WebTransportExplorer = class WebTransportExplorer {
|
|
256
245
|
webTransportServerExplorer;
|
|
257
246
|
webTransportGatewayExplorer;
|
|
258
|
-
logger = new _nestjs_common.Logger(
|
|
247
|
+
logger = new _nestjs_common.Logger(_WebTransportExplorer.name);
|
|
259
248
|
constructor(webTransportServerExplorer, webTransportGatewayExplorer) {
|
|
260
249
|
this.webTransportServerExplorer = webTransportServerExplorer;
|
|
261
250
|
this.webTransportGatewayExplorer = webTransportGatewayExplorer;
|
|
@@ -276,6 +265,7 @@ var WebTransportExplorer = @((0, _nestjs_common.Injectable)()) class WebTranspor
|
|
|
276
265
|
return serverBindings;
|
|
277
266
|
}
|
|
278
267
|
};
|
|
268
|
+
WebTransportExplorer = _WebTransportExplorer = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof WebTransportServerExplorer === "undefined" ? Object : WebTransportServerExplorer, typeof WebTransportGatewayExplorer === "undefined" ? Object : WebTransportGatewayExplorer])], WebTransportExplorer);
|
|
279
269
|
//#endregion
|
|
280
270
|
//#region src/lib/bootstraps/consumers/abstract-stream.consumer.ts
|
|
281
271
|
var AbstractStreamConsumer = class {
|
|
@@ -289,8 +279,9 @@ var AbstractStreamConsumer = class {
|
|
|
289
279
|
};
|
|
290
280
|
//#endregion
|
|
291
281
|
//#region src/lib/bootstraps/consumers/stream-ro.consumer.ts
|
|
292
|
-
var
|
|
293
|
-
|
|
282
|
+
var _StreamROConsumer;
|
|
283
|
+
let StreamROConsumer = _StreamROConsumer = class StreamROConsumer extends AbstractStreamConsumer {
|
|
284
|
+
logger = new _nestjs_common.Logger(_StreamROConsumer.name);
|
|
294
285
|
generateStream(session) {
|
|
295
286
|
return generateUStream(session);
|
|
296
287
|
}
|
|
@@ -301,10 +292,12 @@ var StreamROConsumer = @((0, _nestjs_common.Injectable)()) class StreamROConsume
|
|
|
301
292
|
fireAndForget(() => gateway.onStreamRO?.(stream), this.logger);
|
|
302
293
|
}
|
|
303
294
|
};
|
|
295
|
+
StreamROConsumer = _StreamROConsumer = __decorate([(0, _nestjs_common.Injectable)()], StreamROConsumer);
|
|
304
296
|
//#endregion
|
|
305
297
|
//#region src/lib/bootstraps/consumers/stream-rw.consumer.ts
|
|
306
|
-
var
|
|
307
|
-
|
|
298
|
+
var _StreamRWConsumer;
|
|
299
|
+
let StreamRWConsumer = _StreamRWConsumer = class StreamRWConsumer extends AbstractStreamConsumer {
|
|
300
|
+
logger = new _nestjs_common.Logger(_StreamRWConsumer.name);
|
|
308
301
|
generateStream(session) {
|
|
309
302
|
return generateBStream(session);
|
|
310
303
|
}
|
|
@@ -315,6 +308,7 @@ var StreamRWConsumer = @((0, _nestjs_common.Injectable)()) class StreamRWConsume
|
|
|
315
308
|
fireAndForget(() => gateway.onStreamRW?.(stream), this.logger);
|
|
316
309
|
}
|
|
317
310
|
};
|
|
311
|
+
StreamRWConsumer = _StreamRWConsumer = __decorate([(0, _nestjs_common.Injectable)()], StreamRWConsumer);
|
|
318
312
|
//#endregion
|
|
319
313
|
//#region src/lib/classes/wt-session.ts
|
|
320
314
|
var WtSession = class {
|
|
@@ -333,6 +327,7 @@ var WtSession = class {
|
|
|
333
327
|
};
|
|
334
328
|
//#endregion
|
|
335
329
|
//#region src/lib/bootstraps/server-factory.ts
|
|
330
|
+
var _ServerFactory;
|
|
336
331
|
let webtransport;
|
|
337
332
|
const getLib = eval(`import('@fails-components/webtransport')`).then((module) => {
|
|
338
333
|
webtransport = module;
|
|
@@ -349,10 +344,10 @@ function createHandshakeResponse(request, host, status) {
|
|
|
349
344
|
status
|
|
350
345
|
};
|
|
351
346
|
}
|
|
352
|
-
|
|
347
|
+
let ServerFactory = _ServerFactory = class ServerFactory {
|
|
353
348
|
streamRWConsumer;
|
|
354
349
|
streamROConsumer;
|
|
355
|
-
logger = new _nestjs_common.Logger(
|
|
350
|
+
logger = new _nestjs_common.Logger(_ServerFactory.name);
|
|
356
351
|
constructor(streamRWConsumer, streamROConsumer) {
|
|
357
352
|
this.streamRWConsumer = streamRWConsumer;
|
|
358
353
|
this.streamROConsumer = streamROConsumer;
|
|
@@ -406,9 +401,46 @@ var ServerFactory = @((0, _nestjs_common.Injectable)()) class ServerFactory {
|
|
|
406
401
|
this.streamROConsumer.consume(gateway, webTransportSession, session).catch((error) => this.logger.error(error));
|
|
407
402
|
}
|
|
408
403
|
};
|
|
404
|
+
ServerFactory = _ServerFactory = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof StreamRWConsumer === "undefined" ? Object : StreamRWConsumer, typeof StreamROConsumer === "undefined" ? Object : StreamROConsumer])], ServerFactory);
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/lib/bootstraps/web-transport-bootstrapper.ts
|
|
407
|
+
var _WebTransportBootstrapper;
|
|
408
|
+
let WebTransportBootstrapper = _WebTransportBootstrapper = class WebTransportBootstrapper {
|
|
409
|
+
serverFactory;
|
|
410
|
+
webTransportExplorer;
|
|
411
|
+
logger = new _nestjs_common.Logger(_WebTransportBootstrapper.name);
|
|
412
|
+
h3ServersWithInfo = [];
|
|
413
|
+
constructor(serverFactory, webTransportExplorer) {
|
|
414
|
+
this.serverFactory = serverFactory;
|
|
415
|
+
this.webTransportExplorer = webTransportExplorer;
|
|
416
|
+
}
|
|
417
|
+
async onApplicationBootstrap() {
|
|
418
|
+
const serverBindings = this.webTransportExplorer.discover();
|
|
419
|
+
this.h3ServersWithInfo = await this.serverFactory.createH3Servers(serverBindings);
|
|
420
|
+
await Promise.all(this.h3ServersWithInfo.map(async ({ options, name, h3Server }) => {
|
|
421
|
+
try {
|
|
422
|
+
h3Server.startServer();
|
|
423
|
+
await h3Server.ready;
|
|
424
|
+
this.logger.log(`WebTransport server "${name}" is ready on ${options.host}:${options.port}`);
|
|
425
|
+
} catch (e) {
|
|
426
|
+
this.logger.error(`Failed to start WebTransport server "${name}" on ${options.host}:${options.port}`);
|
|
427
|
+
throw e;
|
|
428
|
+
}
|
|
429
|
+
}));
|
|
430
|
+
}
|
|
431
|
+
async onApplicationShutdown() {
|
|
432
|
+
await Promise.all(this.h3ServersWithInfo.map(async ({ name, h3Server }) => {
|
|
433
|
+
h3Server.stopServer();
|
|
434
|
+
await h3Server.closed;
|
|
435
|
+
this.logger.log(`WebTransport server "${name}" stopped`);
|
|
436
|
+
}));
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
WebTransportBootstrapper = _WebTransportBootstrapper = __decorate([(0, _nestjs_common.Injectable)(), __decorateMetadata("design:paramtypes", [typeof ServerFactory === "undefined" ? Object : ServerFactory, typeof WebTransportExplorer === "undefined" ? Object : WebTransportExplorer])], WebTransportBootstrapper);
|
|
409
440
|
//#endregion
|
|
410
441
|
//#region src/lib/webtransport.module.ts
|
|
411
|
-
|
|
442
|
+
let WebTransportModule = class WebTransportModule {};
|
|
443
|
+
WebTransportModule = __decorate([(0, _nestjs_common.Module)({
|
|
412
444
|
imports: [_nestjs_core.DiscoveryModule],
|
|
413
445
|
providers: [
|
|
414
446
|
ServerFactory,
|
|
@@ -419,10 +451,15 @@ var WebTransportModule = @((0, _nestjs_common.Module)({
|
|
|
419
451
|
WebTransportServerExplorer,
|
|
420
452
|
WebTransportGatewayExplorer
|
|
421
453
|
]
|
|
422
|
-
}))
|
|
454
|
+
})], WebTransportModule);
|
|
423
455
|
//#endregion
|
|
424
456
|
exports.WebTransportGateway = WebTransportGateway;
|
|
425
|
-
exports
|
|
457
|
+
Object.defineProperty(exports, "WebTransportModule", {
|
|
458
|
+
enumerable: true,
|
|
459
|
+
get: function() {
|
|
460
|
+
return WebTransportModule;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
426
463
|
exports.WebTransportServer = WebTransportServer;
|
|
427
464
|
exports.WtSession = WtSession;
|
|
428
465
|
exports.WtStreamRO = WtStreamRO;
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ldtr/nestjs-webtransport",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "NestJS module for creating WebTransport servers and gateways.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"files": [
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
7
9
|
"main": "./dist/index.cjs",
|
|
8
10
|
"types": "./dist/index.d.cts",
|
|
9
11
|
"exports": {
|
|
@@ -40,4 +42,4 @@
|
|
|
40
42
|
"module",
|
|
41
43
|
"typescript"
|
|
42
44
|
]
|
|
43
|
-
}
|
|
45
|
+
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { DiscoveryService } from "@nestjs/core";
|
|
2
|
-
import { HttpServerInit, HttpServerInit as HttpServerInit$1, WebTransportBidirectionalStream, WebTransportReceiveStream, WebTransportSendStream, WebTransportSession } from "@fails-components/webtransport";
|
|
3
|
-
|
|
4
|
-
//#region src/lib/decorators/webtransport-gateway.decorator.d.ts
|
|
5
|
-
type WebTransportGatewayOptions = {
|
|
6
|
-
readonly path: string;
|
|
7
|
-
readonly server: string;
|
|
8
|
-
};
|
|
9
|
-
declare function WebTransportGateway(options: WebTransportGatewayOptions): ClassDecorator;
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/lib/decorators/webtransport-server.decorator.d.ts
|
|
12
|
-
interface WebTransportServerOptions {
|
|
13
|
-
readonly name: string;
|
|
14
|
-
}
|
|
15
|
-
declare function WebTransportServer(options: WebTransportServerOptions): ClassDecorator;
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/lib/explorers/webtransport-server.explorer.d.ts
|
|
18
|
-
type WebTransportServerOptionsFactory = {
|
|
19
|
-
options(): HttpServerInit$1 | Promise<HttpServerInit$1>;
|
|
20
|
-
};
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/lib/classes/wt-session.d.ts
|
|
23
|
-
declare class WtSession {
|
|
24
|
-
private readonly webTransportSession;
|
|
25
|
-
constructor(webTransportSession: WebTransportSession);
|
|
26
|
-
createStreamWO(): Promise<WtStreamWO>;
|
|
27
|
-
createStreamRW(): Promise<WtStreamRW>;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/lib/classes/wt-stream.d.ts
|
|
31
|
-
declare abstract class AbstractWtStream<TWebStream> {
|
|
32
|
-
readonly session: WtSession;
|
|
33
|
-
protected readonly webTransportStream: TWebStream;
|
|
34
|
-
protected constructor(session: WtSession, webTransportStream: TWebStream);
|
|
35
|
-
}
|
|
36
|
-
interface WtReadableStream {
|
|
37
|
-
read(): AsyncIterableIterator<Uint8Array>;
|
|
38
|
-
closeReadable(): Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
interface WtWritableStream {
|
|
41
|
-
write(data: Uint8Array): Promise<void>;
|
|
42
|
-
closeWritable(): Promise<void>;
|
|
43
|
-
}
|
|
44
|
-
declare class WtStreamRW extends AbstractWtStream<WebTransportBidirectionalStream> implements WtReadableStream, WtWritableStream {
|
|
45
|
-
private readonly readableStreamHandler;
|
|
46
|
-
private readonly writableStreamHandler;
|
|
47
|
-
constructor(session: WtSession, webTransportStream: WebTransportBidirectionalStream);
|
|
48
|
-
read(): AsyncIterableIterator<Uint8Array>;
|
|
49
|
-
write(data: Uint8Array): Promise<void>;
|
|
50
|
-
closeReadable(): Promise<void>;
|
|
51
|
-
closeWritable(): Promise<void>;
|
|
52
|
-
close(): Promise<void>;
|
|
53
|
-
}
|
|
54
|
-
declare class WtStreamRO extends AbstractWtStream<WebTransportReceiveStream> implements WtReadableStream {
|
|
55
|
-
private readonly readableStreamHandler;
|
|
56
|
-
constructor(session: WtSession, webTransportStream: WebTransportReceiveStream);
|
|
57
|
-
read(): AsyncIterableIterator<Uint8Array>;
|
|
58
|
-
closeReadable(): Promise<void>;
|
|
59
|
-
}
|
|
60
|
-
declare class WtStreamWO extends AbstractWtStream<WebTransportSendStream> implements WtWritableStream {
|
|
61
|
-
private readonly writableStreamHandler;
|
|
62
|
-
constructor(session: WtSession, webTransportStream: WebTransportSendStream);
|
|
63
|
-
write(data: Uint8Array): Promise<void>;
|
|
64
|
-
closeWritable(): Promise<void>;
|
|
65
|
-
}
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region src/lib/bootstraps/types.d.ts
|
|
68
|
-
type WebTransportRequestHeader = {
|
|
69
|
-
readonly ':path': string;
|
|
70
|
-
};
|
|
71
|
-
type WebTransportRequest = {
|
|
72
|
-
readonly header: WebTransportRequestHeader;
|
|
73
|
-
};
|
|
74
|
-
//#endregion
|
|
75
|
-
//#region src/lib/explorers/webtransport-gateway.explorer.d.ts
|
|
76
|
-
type WebTransportGatewayLifecycle = {
|
|
77
|
-
allowRequest?(request: WebTransportRequest): void | Promise<void>;
|
|
78
|
-
onSession?(session: WtSession): void | Promise<void>;
|
|
79
|
-
onSessionClosed?(session: WtSession): void | Promise<void>;
|
|
80
|
-
onStreamRW?(stream: WtStreamRW): void | Promise<void>;
|
|
81
|
-
onStreamRO?(stream: WtStreamRO): void | Promise<void>;
|
|
82
|
-
};
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region src/lib/webtransport.module.d.ts
|
|
85
|
-
declare class WebTransportModule {}
|
|
86
|
-
//#endregion
|
|
87
|
-
export { type HttpServerInit, WebTransportGateway, type WebTransportGatewayLifecycle, type WebTransportGatewayOptions, WebTransportModule, WebTransportServer, type WebTransportServerOptions, type WebTransportServerOptionsFactory, WtSession, WtStreamRO, WtStreamRW, WtStreamWO };
|
package/dist/index.mjs
DELETED
|
@@ -1,423 +0,0 @@
|
|
|
1
|
-
import { HttpException, Injectable, Logger, Module, applyDecorators } from "@nestjs/common";
|
|
2
|
-
import { DiscoveryModule, DiscoveryService } from "@nestjs/core";
|
|
3
|
-
//#region src/lib/decorators/webtransport-gateway.decorator.ts
|
|
4
|
-
const DiscoverableWebTransportGateway = DiscoveryService.createDecorator();
|
|
5
|
-
function WebTransportGateway(options) {
|
|
6
|
-
return applyDecorators(Injectable(), DiscoverableWebTransportGateway(options));
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
//#region src/lib/decorators/webtransport-server.decorator.ts
|
|
10
|
-
const DiscoverableWebTransportServer = DiscoveryService.createDecorator();
|
|
11
|
-
function WebTransportServer(options) {
|
|
12
|
-
return applyDecorators(Injectable(), DiscoverableWebTransportServer(options));
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/lib/bootstraps/helpers.ts
|
|
16
|
-
async function* generateSession(stream) {
|
|
17
|
-
const reader = stream.getReader();
|
|
18
|
-
try {
|
|
19
|
-
while (true) {
|
|
20
|
-
const { done, value } = await reader.read();
|
|
21
|
-
if (done) break;
|
|
22
|
-
yield value;
|
|
23
|
-
}
|
|
24
|
-
} finally {
|
|
25
|
-
reader.releaseLock();
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
async function* generateBStream(session) {
|
|
29
|
-
const reader = session.incomingBidirectionalStreams.getReader();
|
|
30
|
-
try {
|
|
31
|
-
while (true) {
|
|
32
|
-
const { done, value } = await reader.read();
|
|
33
|
-
if (done) break;
|
|
34
|
-
yield value;
|
|
35
|
-
}
|
|
36
|
-
} finally {
|
|
37
|
-
reader.releaseLock();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
async function* generateUStream(session) {
|
|
41
|
-
const reader = session.incomingUnidirectionalStreams.getReader();
|
|
42
|
-
try {
|
|
43
|
-
while (true) {
|
|
44
|
-
const { done, value } = await reader.read();
|
|
45
|
-
if (done) break;
|
|
46
|
-
yield value;
|
|
47
|
-
}
|
|
48
|
-
} finally {
|
|
49
|
-
reader.releaseLock();
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async function* generateChunks(reader) {
|
|
53
|
-
try {
|
|
54
|
-
while (true) {
|
|
55
|
-
const { done, value } = await reader.read();
|
|
56
|
-
if (done) break;
|
|
57
|
-
yield value;
|
|
58
|
-
}
|
|
59
|
-
} finally {
|
|
60
|
-
reader.releaseLock();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function fireAndForget(task, logger) {
|
|
64
|
-
if (!task) return;
|
|
65
|
-
try {
|
|
66
|
-
Promise.resolve(task()).catch((error) => {
|
|
67
|
-
logger?.error(error);
|
|
68
|
-
});
|
|
69
|
-
} catch (error) {
|
|
70
|
-
logger?.error(error);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/lib/classes/wt-stream.ts
|
|
75
|
-
var AbstractStreamHandler = class {
|
|
76
|
-
closed = false;
|
|
77
|
-
async close() {
|
|
78
|
-
if (this.closed) return;
|
|
79
|
-
this.closed = true;
|
|
80
|
-
await this.localClose();
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
var ReadableStreamHandler = class extends AbstractStreamHandler {
|
|
84
|
-
reader;
|
|
85
|
-
chunks;
|
|
86
|
-
constructor(reader) {
|
|
87
|
-
super();
|
|
88
|
-
this.reader = reader;
|
|
89
|
-
this.chunks = generateChunks(this.reader);
|
|
90
|
-
}
|
|
91
|
-
read() {
|
|
92
|
-
if (this.closed) throw new Error("Can't read stream");
|
|
93
|
-
return this.chunks;
|
|
94
|
-
}
|
|
95
|
-
async localClose() {
|
|
96
|
-
await this.reader.cancel();
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
var WritableStreamHandler = class extends AbstractStreamHandler {
|
|
100
|
-
writer;
|
|
101
|
-
constructor(writer) {
|
|
102
|
-
super();
|
|
103
|
-
this.writer = writer;
|
|
104
|
-
}
|
|
105
|
-
async write(chunk) {
|
|
106
|
-
if (this.closed) throw new Error("Can't write stream");
|
|
107
|
-
await this.writer.write(chunk);
|
|
108
|
-
}
|
|
109
|
-
async localClose() {
|
|
110
|
-
await this.writer.close();
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
var AbstractWtStream = class {
|
|
114
|
-
session;
|
|
115
|
-
webTransportStream;
|
|
116
|
-
constructor(session, webTransportStream) {
|
|
117
|
-
this.session = session;
|
|
118
|
-
this.webTransportStream = webTransportStream;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
var WtStreamRW = class extends AbstractWtStream {
|
|
122
|
-
readableStreamHandler;
|
|
123
|
-
writableStreamHandler;
|
|
124
|
-
constructor(session, webTransportStream) {
|
|
125
|
-
super(session, webTransportStream);
|
|
126
|
-
this.readableStreamHandler = new ReadableStreamHandler(webTransportStream.readable.getReader());
|
|
127
|
-
this.writableStreamHandler = new WritableStreamHandler(webTransportStream.writable.getWriter());
|
|
128
|
-
}
|
|
129
|
-
read() {
|
|
130
|
-
return this.readableStreamHandler.read();
|
|
131
|
-
}
|
|
132
|
-
async write(data) {
|
|
133
|
-
await this.writableStreamHandler.write(data);
|
|
134
|
-
}
|
|
135
|
-
async closeReadable() {
|
|
136
|
-
await this.readableStreamHandler.close();
|
|
137
|
-
}
|
|
138
|
-
async closeWritable() {
|
|
139
|
-
await this.writableStreamHandler.close();
|
|
140
|
-
}
|
|
141
|
-
async close() {
|
|
142
|
-
await Promise.all([this.closeReadable(), this.closeWritable()]);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
var WtStreamRO = class extends AbstractWtStream {
|
|
146
|
-
readableStreamHandler;
|
|
147
|
-
constructor(session, webTransportStream) {
|
|
148
|
-
super(session, webTransportStream);
|
|
149
|
-
this.readableStreamHandler = new ReadableStreamHandler(webTransportStream.getReader());
|
|
150
|
-
}
|
|
151
|
-
read() {
|
|
152
|
-
return this.readableStreamHandler.read();
|
|
153
|
-
}
|
|
154
|
-
async closeReadable() {
|
|
155
|
-
await this.readableStreamHandler.close();
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
var WtStreamWO = class extends AbstractWtStream {
|
|
159
|
-
writableStreamHandler;
|
|
160
|
-
constructor(session, webTransportStream) {
|
|
161
|
-
super(session, webTransportStream);
|
|
162
|
-
this.writableStreamHandler = new WritableStreamHandler(webTransportStream.getWriter());
|
|
163
|
-
}
|
|
164
|
-
async write(data) {
|
|
165
|
-
await this.writableStreamHandler.write(data);
|
|
166
|
-
}
|
|
167
|
-
async closeWritable() {
|
|
168
|
-
await this.writableStreamHandler.close();
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
//#endregion
|
|
172
|
-
//#region src/lib/explorers/webtransport-gateway.explorer.ts
|
|
173
|
-
var WebTransportGatewayExplorer = @Injectable() class {
|
|
174
|
-
discoveryService;
|
|
175
|
-
constructor(discoveryService) {
|
|
176
|
-
this.discoveryService = discoveryService;
|
|
177
|
-
}
|
|
178
|
-
discover(serverNames) {
|
|
179
|
-
const gatewaysByNameByPath = /* @__PURE__ */ new Map();
|
|
180
|
-
const wrappers = this.discoveryService.getProviders({ metadataKey: DiscoverableWebTransportGateway.KEY });
|
|
181
|
-
for (const wrapper of wrappers) {
|
|
182
|
-
const metadata = this.discoveryService.getMetadataByDecorator(DiscoverableWebTransportGateway, wrapper);
|
|
183
|
-
if (!metadata || !wrapper.metatype) continue;
|
|
184
|
-
const { server } = metadata;
|
|
185
|
-
let { path } = metadata;
|
|
186
|
-
if (!path.startsWith("/")) path = "/" + path;
|
|
187
|
-
const gateway = wrapper.instance;
|
|
188
|
-
if (!gatewaysByNameByPath.has(server)) {
|
|
189
|
-
if (!serverNames.includes(server)) throw new Error(`@WebTransportGateway() server name doesn't exist: ${server}`);
|
|
190
|
-
gatewaysByNameByPath.set(server, /* @__PURE__ */ new Map());
|
|
191
|
-
}
|
|
192
|
-
if (gatewaysByNameByPath.get(server).has(path)) throw new Error(`Duplicate @WebTransportGateway() path: ${path}`);
|
|
193
|
-
gatewaysByNameByPath.get(server).set(path, gateway);
|
|
194
|
-
}
|
|
195
|
-
return gatewaysByNameByPath;
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
//#endregion
|
|
199
|
-
//#region src/lib/explorers/webtransport-server.explorer.ts
|
|
200
|
-
var WebTransportServerExplorer = @Injectable() class {
|
|
201
|
-
discoveryService;
|
|
202
|
-
constructor(discoveryService) {
|
|
203
|
-
this.discoveryService = discoveryService;
|
|
204
|
-
}
|
|
205
|
-
discover() {
|
|
206
|
-
const serversByName = /* @__PURE__ */ new Map();
|
|
207
|
-
const wrappers = this.discoveryService.getProviders({ metadataKey: DiscoverableWebTransportServer.KEY });
|
|
208
|
-
for (const wrapper of wrappers) {
|
|
209
|
-
const metadata = this.discoveryService.getMetadataByDecorator(DiscoverableWebTransportServer, wrapper);
|
|
210
|
-
if (!metadata || !wrapper.metatype) continue;
|
|
211
|
-
const { name } = metadata;
|
|
212
|
-
if (serversByName.has(name)) throw new Error(`Duplicate @WebTransportServer() name: ${name}`);
|
|
213
|
-
const server = wrapper.instance;
|
|
214
|
-
serversByName.set(name, server);
|
|
215
|
-
}
|
|
216
|
-
return serversByName;
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
//#endregion
|
|
220
|
-
//#region src/lib/bootstraps/web-transport-bootstrapper.ts
|
|
221
|
-
var WebTransportBootstrapper = @Injectable() class WebTransportBootstrapper {
|
|
222
|
-
serverFactory;
|
|
223
|
-
webTransportExplorer;
|
|
224
|
-
logger = new Logger(WebTransportBootstrapper.name);
|
|
225
|
-
h3ServersWithInfo = [];
|
|
226
|
-
constructor(serverFactory, webTransportExplorer) {
|
|
227
|
-
this.serverFactory = serverFactory;
|
|
228
|
-
this.webTransportExplorer = webTransportExplorer;
|
|
229
|
-
}
|
|
230
|
-
async onApplicationBootstrap() {
|
|
231
|
-
const serverBindings = this.webTransportExplorer.discover();
|
|
232
|
-
this.h3ServersWithInfo = await this.serverFactory.createH3Servers(serverBindings);
|
|
233
|
-
await Promise.all(this.h3ServersWithInfo.map(async ({ options, name, h3Server }) => {
|
|
234
|
-
try {
|
|
235
|
-
h3Server.startServer();
|
|
236
|
-
await h3Server.ready;
|
|
237
|
-
this.logger.log(`WebTransport server "${name}" is ready on ${options.host}:${options.port}`);
|
|
238
|
-
} catch (e) {
|
|
239
|
-
this.logger.error(`Failed to start WebTransport server "${name}" on ${options.host}:${options.port}`);
|
|
240
|
-
throw e;
|
|
241
|
-
}
|
|
242
|
-
}));
|
|
243
|
-
}
|
|
244
|
-
async onApplicationShutdown() {
|
|
245
|
-
await Promise.all(this.h3ServersWithInfo.map(async ({ name, h3Server }) => {
|
|
246
|
-
h3Server.stopServer();
|
|
247
|
-
await h3Server.closed;
|
|
248
|
-
this.logger.log(`WebTransport server "${name}" stopped`);
|
|
249
|
-
}));
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
//#endregion
|
|
253
|
-
//#region src/lib/explorers/web-transport.explorer.ts
|
|
254
|
-
var WebTransportExplorer = @Injectable() class WebTransportExplorer {
|
|
255
|
-
webTransportServerExplorer;
|
|
256
|
-
webTransportGatewayExplorer;
|
|
257
|
-
logger = new Logger(WebTransportExplorer.name);
|
|
258
|
-
constructor(webTransportServerExplorer, webTransportGatewayExplorer) {
|
|
259
|
-
this.webTransportServerExplorer = webTransportServerExplorer;
|
|
260
|
-
this.webTransportGatewayExplorer = webTransportGatewayExplorer;
|
|
261
|
-
}
|
|
262
|
-
discover() {
|
|
263
|
-
const serversByName = this.webTransportServerExplorer.discover();
|
|
264
|
-
const gatewaysByNameByPath = this.webTransportGatewayExplorer.discover(Array.from(serversByName.keys()));
|
|
265
|
-
const serverBindings = [];
|
|
266
|
-
serversByName.forEach((server, name) => {
|
|
267
|
-
const gatewaysByPath = gatewaysByNameByPath.get(name);
|
|
268
|
-
if (gatewaysByPath === void 0) this.logger.warn(`WebTransport server "${name}" has no gateways, skipping`);
|
|
269
|
-
else serverBindings.push({
|
|
270
|
-
server,
|
|
271
|
-
name,
|
|
272
|
-
gatewaysByPath
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
return serverBindings;
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
//#endregion
|
|
279
|
-
//#region src/lib/bootstraps/consumers/abstract-stream.consumer.ts
|
|
280
|
-
var AbstractStreamConsumer = class {
|
|
281
|
-
async consume(gateway, webTransportSession, session) {
|
|
282
|
-
for await (const webTransportStream of this.generateStream(webTransportSession)) this.handleStream(gateway, session, webTransportStream);
|
|
283
|
-
}
|
|
284
|
-
handleStream(gateway, session, webTransportStream) {
|
|
285
|
-
const stream = this.createStream(session, webTransportStream);
|
|
286
|
-
this.consumeHook(gateway, stream);
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
//#endregion
|
|
290
|
-
//#region src/lib/bootstraps/consumers/stream-ro.consumer.ts
|
|
291
|
-
var StreamROConsumer = @Injectable() class StreamROConsumer extends AbstractStreamConsumer {
|
|
292
|
-
logger = new Logger(StreamROConsumer.name);
|
|
293
|
-
generateStream(session) {
|
|
294
|
-
return generateUStream(session);
|
|
295
|
-
}
|
|
296
|
-
createStream(session, webTransportStream) {
|
|
297
|
-
return new WtStreamRO(session, webTransportStream);
|
|
298
|
-
}
|
|
299
|
-
consumeHook(gateway, stream) {
|
|
300
|
-
fireAndForget(() => gateway.onStreamRO?.(stream), this.logger);
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
//#endregion
|
|
304
|
-
//#region src/lib/bootstraps/consumers/stream-rw.consumer.ts
|
|
305
|
-
var StreamRWConsumer = @Injectable() class StreamRWConsumer extends AbstractStreamConsumer {
|
|
306
|
-
logger = new Logger(StreamRWConsumer.name);
|
|
307
|
-
generateStream(session) {
|
|
308
|
-
return generateBStream(session);
|
|
309
|
-
}
|
|
310
|
-
createStream(session, webTransportStream) {
|
|
311
|
-
return new WtStreamRW(session, webTransportStream);
|
|
312
|
-
}
|
|
313
|
-
consumeHook(gateway, stream) {
|
|
314
|
-
fireAndForget(() => gateway.onStreamRW?.(stream), this.logger);
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
|
-
//#endregion
|
|
318
|
-
//#region src/lib/classes/wt-session.ts
|
|
319
|
-
var WtSession = class {
|
|
320
|
-
webTransportSession;
|
|
321
|
-
constructor(webTransportSession) {
|
|
322
|
-
this.webTransportSession = webTransportSession;
|
|
323
|
-
}
|
|
324
|
-
async createStreamWO() {
|
|
325
|
-
const stream = await this.webTransportSession.createUnidirectionalStream();
|
|
326
|
-
return new WtStreamWO(this, stream);
|
|
327
|
-
}
|
|
328
|
-
async createStreamRW() {
|
|
329
|
-
const stream = await this.webTransportSession.createBidirectionalStream();
|
|
330
|
-
return new WtStreamRW(this, stream);
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/lib/bootstraps/server-factory.ts
|
|
335
|
-
let webtransport;
|
|
336
|
-
const getLib = eval(`import('@fails-components/webtransport')`).then((module) => {
|
|
337
|
-
webtransport = module;
|
|
338
|
-
});
|
|
339
|
-
function createHandshakeResponse(request, host, status) {
|
|
340
|
-
const url = new URL(request.header[":path"], `https://${host}`);
|
|
341
|
-
return {
|
|
342
|
-
...request,
|
|
343
|
-
path: url.pathname,
|
|
344
|
-
header: {
|
|
345
|
-
...request.header,
|
|
346
|
-
":path": url.pathname
|
|
347
|
-
},
|
|
348
|
-
status
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
var ServerFactory = @Injectable() class ServerFactory {
|
|
352
|
-
streamRWConsumer;
|
|
353
|
-
streamROConsumer;
|
|
354
|
-
logger = new Logger(ServerFactory.name);
|
|
355
|
-
constructor(streamRWConsumer, streamROConsumer) {
|
|
356
|
-
this.streamRWConsumer = streamRWConsumer;
|
|
357
|
-
this.streamROConsumer = streamROConsumer;
|
|
358
|
-
}
|
|
359
|
-
async createH3Servers(serverBindings) {
|
|
360
|
-
await getLib;
|
|
361
|
-
const h3ServersWithInfo = [];
|
|
362
|
-
for (const { server, name, gatewaysByPath } of serverBindings) {
|
|
363
|
-
const options = await server.options();
|
|
364
|
-
const h3Server = this.createH3Server(options, gatewaysByPath);
|
|
365
|
-
h3ServersWithInfo.push({
|
|
366
|
-
options,
|
|
367
|
-
h3Server,
|
|
368
|
-
name
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
return h3ServersWithInfo;
|
|
372
|
-
}
|
|
373
|
-
createH3Server(options, gatewaysByPath) {
|
|
374
|
-
const h3Server = new webtransport.Http3Server(options);
|
|
375
|
-
h3Server.setRequestCallback(async (request) => {
|
|
376
|
-
const status = await this.getRequestStatus(request, gatewaysByPath);
|
|
377
|
-
return createHandshakeResponse(request, options.host, status);
|
|
378
|
-
});
|
|
379
|
-
for (const [path, gateway] of gatewaysByPath.entries()) this.consumeSession(gateway, h3Server, path).catch((error) => this.logger.error(error));
|
|
380
|
-
return h3Server;
|
|
381
|
-
}
|
|
382
|
-
async getRequestStatus(request, gatewaysByPath) {
|
|
383
|
-
const { pathname } = new URL(request.header[":path"], "https://0.0.0.0");
|
|
384
|
-
const gateway = gatewaysByPath.get(pathname);
|
|
385
|
-
if (gateway === void 0) return 404;
|
|
386
|
-
try {
|
|
387
|
-
await gateway.allowRequest?.(request);
|
|
388
|
-
return 200;
|
|
389
|
-
} catch (e) {
|
|
390
|
-
if (e instanceof HttpException) return e.getStatus();
|
|
391
|
-
return 400;
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
async consumeSession(gateway, h3Server, path) {
|
|
395
|
-
const stream = h3Server.sessionStream(path);
|
|
396
|
-
for await (const session of generateSession(stream)) this.handleSession(gateway, session);
|
|
397
|
-
}
|
|
398
|
-
handleSession(gateway, webTransportSession) {
|
|
399
|
-
const session = new WtSession(webTransportSession);
|
|
400
|
-
fireAndForget(() => gateway.onSession?.(session), this.logger);
|
|
401
|
-
webTransportSession.closed.catch((error) => this.logger.error(error)).finally(() => {
|
|
402
|
-
fireAndForget(() => gateway.onSessionClosed?.(session), this.logger);
|
|
403
|
-
});
|
|
404
|
-
this.streamRWConsumer.consume(gateway, webTransportSession, session).catch((error) => this.logger.error(error));
|
|
405
|
-
this.streamROConsumer.consume(gateway, webTransportSession, session).catch((error) => this.logger.error(error));
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
//#endregion
|
|
409
|
-
//#region src/lib/webtransport.module.ts
|
|
410
|
-
var WebTransportModule = @Module({
|
|
411
|
-
imports: [DiscoveryModule],
|
|
412
|
-
providers: [
|
|
413
|
-
ServerFactory,
|
|
414
|
-
StreamRWConsumer,
|
|
415
|
-
StreamROConsumer,
|
|
416
|
-
WebTransportExplorer,
|
|
417
|
-
WebTransportBootstrapper,
|
|
418
|
-
WebTransportServerExplorer,
|
|
419
|
-
WebTransportGatewayExplorer
|
|
420
|
-
]
|
|
421
|
-
}) class {};
|
|
422
|
-
//#endregion
|
|
423
|
-
export { WebTransportGateway, WebTransportModule, WebTransportServer, WtSession, WtStreamRO, WtStreamRW, WtStreamWO };
|