@fluojs/websockets 1.0.3 → 1.0.5
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.ko.md +2 -2
- package/README.md +2 -2
- package/dist/bun/bun-service.d.ts +1 -2
- package/dist/bun/bun-service.d.ts.map +1 -1
- package/dist/bun/bun-service.js +7 -23
- package/dist/bun/bun-types.d.ts +7 -2
- package/dist/bun/bun-types.d.ts.map +1 -1
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts +1 -2
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts.map +1 -1
- package/dist/cloudflare-workers/cloudflare-workers-service.js +7 -23
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts +7 -2
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts.map +1 -1
- package/dist/deno/deno-service.d.ts +1 -2
- package/dist/deno/deno-service.d.ts.map +1 -1
- package/dist/deno/deno-service.js +7 -23
- package/dist/deno/deno-types.d.ts +7 -2
- package/dist/deno/deno-types.d.ts.map +1 -1
- package/dist/internal/shared.d.ts +22 -0
- package/dist/internal/shared.d.ts.map +1 -1
- package/dist/internal/shared.js +87 -9
- package/dist/node/node-service.d.ts.map +1 -1
- package/dist/node/node-service.js +20 -10
- package/dist/node/node-types.d.ts +4 -61
- package/dist/node/node-types.d.ts.map +1 -1
- package/dist/types.d.ts +61 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -8
package/README.ko.md
CHANGED
|
@@ -67,7 +67,7 @@ class MetricsGateway {
|
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
### Server-Backed Node adapter
|
|
70
|
-
Server-backed Node adapter(Node.js, Express, Fastify)에서는 전용 listener port를 사용할 수 있습니다. Fetch-style runtime(`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, `@fluojs/websockets/cloudflare-workers`)은 `serverBacked`를 거부합니다.
|
|
70
|
+
Server-backed Node adapter(Node.js, Express, Fastify)에서는 전용 listener port를 사용할 수 있습니다. 테스트나 동적 host에서 운영체제가 ephemeral listener port를 원자적으로 할당하게 하려면 `serverBacked.port: 0`을 사용합니다. Fetch-style runtime(`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, `@fluojs/websockets/cloudflare-workers`)은 `serverBacked`를 거부합니다.
|
|
71
71
|
|
|
72
72
|
```typescript
|
|
73
73
|
@WebSocketGateway({
|
|
@@ -102,7 +102,7 @@ WebSocketModule.forRoot({
|
|
|
102
102
|
});
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
옵션을 생략하면 `@fluojs/websockets`는 동시 연결 수, inbound payload 크기, pending message buffer, shutdown cleanup에 bounded default를 적용합니다. 기본값은 `maxConnections: 1000`, `maxPayloadBytes: 1 MiB`, `buffer.maxPendingMessagesPerSocket: 256`, `shutdown.timeoutMs: 5000`, Node heartbeat interval `30s`, Node backpressure `maxBufferedAmountBytes: 1 MiB`와 drop behavior입니다. 또한 server-backed Node listener는 `heartbeat.enabled`를 명시적으로 `false`로 두지 않는 한 heartbeat timer를 활성화합니다. Node shutdown은 shutdown이 시작된 뒤 in-flight async upgrade를 거절하고, 애플리케이션 shutdown 시 추적 중인 websocket 클라이언트를 닫고, `shutdown.timeoutMs` 범위 안에서 `@OnDisconnect()` cleanup이 마무리될 수 있도록 bounded 기회를 제공합니다. 공식 fetch-style runtime module(`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, `@fluojs/websockets/cloudflare-workers`)
|
|
105
|
+
옵션을 생략하면 `@fluojs/websockets`는 동시 연결 수, inbound payload 크기, pending message buffer, shutdown cleanup에 bounded default를 적용합니다. 기본값은 `maxConnections: 1000`, `maxPayloadBytes: 1 MiB`, `buffer.maxPendingMessagesPerSocket: 256`, `shutdown.timeoutMs: 5000`, Node heartbeat interval `30s`, Node backpressure `maxBufferedAmountBytes: 1 MiB`와 drop behavior입니다. 또한 server-backed Node listener는 `heartbeat.enabled`를 명시적으로 `false`로 두지 않는 한 heartbeat timer를 활성화합니다. Node shutdown은 shutdown이 시작된 뒤 in-flight async upgrade를 거절하고, 애플리케이션 shutdown 시 추적 중인 websocket 클라이언트를 닫고, `shutdown.timeoutMs` 범위 안에서 `@OnDisconnect()` cleanup이 마무리될 수 있도록 bounded 기회를 제공합니다. 공식 fetch-style runtime module(`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, `@fluojs/websockets/cloudflare-workers`)은 `Request` typed upgrade guard를 노출하며, 애플리케이션 shutdown 중 동일한 bounded close와 disconnect cleanup 동작을 제공합니다.
|
|
106
106
|
|
|
107
107
|
## 바이너리 페이로드
|
|
108
108
|
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ class MetricsGateway {
|
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
### Server-Backed Node Adapters
|
|
70
|
-
For server-backed Node adapters (Node.js, Express, Fastify), you can opt into a dedicated listener port. Fetch-style runtimes (`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, and `@fluojs/websockets/cloudflare-workers`) reject `serverBacked`.
|
|
70
|
+
For server-backed Node adapters (Node.js, Express, Fastify), you can opt into a dedicated listener port. Use `serverBacked.port: 0` when tests or dynamic hosts should let the operating system allocate an ephemeral listener port atomically. Fetch-style runtimes (`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, and `@fluojs/websockets/cloudflare-workers`) reject `serverBacked`.
|
|
71
71
|
|
|
72
72
|
```typescript
|
|
73
73
|
@WebSocketGateway({
|
|
@@ -102,7 +102,7 @@ WebSocketModule.forRoot({
|
|
|
102
102
|
});
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
When omitted, `@fluojs/websockets` applies bounded defaults for concurrent connections, inbound payload size, pending message buffers, and shutdown cleanup. Default settings are `maxConnections: 1000`, `maxPayloadBytes: 1 MiB`, `buffer.maxPendingMessagesPerSocket: 256`, `shutdown.timeoutMs: 5000`, Node heartbeat interval `30s`, and Node backpressure `maxBufferedAmountBytes: 1 MiB` with drop behavior. Server-backed Node listeners enable heartbeat timers unless you explicitly set `heartbeat.enabled` to `false`. Node shutdown rejects in-flight async upgrades once shutdown begins, will close tracked websocket clients during application shutdown, and gives `@OnDisconnect()` cleanup a bounded chance to finish within `shutdown.timeoutMs`. The official fetch-style runtime modules (`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, and `@fluojs/websockets/cloudflare-workers`) provide the same bounded close and disconnect cleanup behavior during application shutdown.
|
|
105
|
+
When omitted, `@fluojs/websockets` applies bounded defaults for concurrent connections, inbound payload size, pending message buffers, and shutdown cleanup. Default settings are `maxConnections: 1000`, `maxPayloadBytes: 1 MiB`, `buffer.maxPendingMessagesPerSocket: 256`, `shutdown.timeoutMs: 5000`, Node heartbeat interval `30s`, and Node backpressure `maxBufferedAmountBytes: 1 MiB` with drop behavior. Server-backed Node listeners enable heartbeat timers unless you explicitly set `heartbeat.enabled` to `false`. Node shutdown rejects in-flight async upgrades once shutdown begins, will close tracked websocket clients during application shutdown, and gives `@OnDisconnect()` cleanup a bounded chance to finish within `shutdown.timeoutMs`. The official fetch-style runtime modules (`@fluojs/websockets/bun`, `@fluojs/websockets/deno`, and `@fluojs/websockets/cloudflare-workers`) expose `Request`-typed upgrade guards and provide the same bounded close and disconnect cleanup behavior during application shutdown.
|
|
106
106
|
|
|
107
107
|
## Binary Payloads
|
|
108
108
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
3
2
|
import type { HttpApplicationAdapter } from '@fluojs/http';
|
|
3
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
4
4
|
import type { WebSocketRoomService } from '../types.js';
|
|
5
5
|
import type { WebSocketModuleOptions } from './bun-types.js';
|
|
6
6
|
/**
|
|
@@ -22,7 +22,6 @@ export declare class BunWebSocketGatewayLifecycleService implements OnApplicatio
|
|
|
22
22
|
private readonly socketStates;
|
|
23
23
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, adapter: HttpApplicationAdapter, moduleOptions: WebSocketModuleOptions);
|
|
24
24
|
onApplicationBootstrap(): Promise<void>;
|
|
25
|
-
private assertNoServerBackedGatewayOptIn;
|
|
26
25
|
onApplicationShutdown(): Promise<void>;
|
|
27
26
|
onModuleDestroy(): Promise<void>;
|
|
28
27
|
private createBinding;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun-service.d.ts","sourceRoot":"","sources":["../../src/bun/bun-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"bun-service.d.ts","sourceRoot":"","sources":["../../src/bun/bun-service.ts"],"names":[],"mappings":"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"}
|
package/dist/bun/bun-service.js
CHANGED
|
@@ -6,7 +6,7 @@ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.descrip
|
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
7
|
import { Inject } from '@fluojs/core';
|
|
8
8
|
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
9
|
-
import { dispatchGatewayDisconnect, dispatchGatewayMessage,
|
|
9
|
+
import { assertNoFetchStyleServerBackedGatewayOptIn, discoverGatewayDescriptors, dispatchGatewayDisconnect, dispatchGatewayMessage, isFinitePositiveInteger, normalizeGatewayPath, resolveGatewayInstance, resolveSupportedFetchStyleRealtimeCapability, runGatewayHandlers } from '../internal/shared.js';
|
|
10
10
|
import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
11
11
|
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
12
12
|
const DEFAULT_MAX_WEBSOCKET_CONNECTIONS = 1_000;
|
|
@@ -16,19 +16,6 @@ const LIFECYCLE_LOG_CONTEXT = 'WebSocketGatewayLifecycleService';
|
|
|
16
16
|
function hasBunWebSocketBindingHost(adapter) {
|
|
17
17
|
return 'configureWebSocketBinding' in adapter && typeof adapter.configureWebSocketBinding === 'function';
|
|
18
18
|
}
|
|
19
|
-
function resolveSupportedFetchStyleRealtimeCapability(adapter) {
|
|
20
|
-
if (typeof adapter.getRealtimeCapability !== 'function') {
|
|
21
|
-
throw new Error('Bun WebSocket gateway bootstrap requires an HTTP adapter with getRealtimeCapability(). Use @fluojs/platform-bun together with @fluojs/websockets/bun.');
|
|
22
|
-
}
|
|
23
|
-
const capability = adapter.getRealtimeCapability();
|
|
24
|
-
if (capability.kind !== 'fetch-style' || capability.contract !== 'raw-websocket-expansion') {
|
|
25
|
-
throw new Error('Bun WebSocket gateway bootstrap requires a fetch-style raw-websocket-expansion realtime capability from the selected HTTP adapter.');
|
|
26
|
-
}
|
|
27
|
-
if (capability.support !== 'supported') {
|
|
28
|
-
throw new Error(`Bun WebSocket gateway bootstrap requires supported fetch-style websocket hosting. ${capability.reason}`);
|
|
29
|
-
}
|
|
30
|
-
return capability;
|
|
31
|
-
}
|
|
32
19
|
function isHttpExceptionLike(error) {
|
|
33
20
|
return typeof error === 'object' && error !== null && 'message' in error && 'status' in error;
|
|
34
21
|
}
|
|
@@ -80,21 +67,18 @@ class BunWebSocketGatewayLifecycleService {
|
|
|
80
67
|
if (descriptors.length === 0) {
|
|
81
68
|
return;
|
|
82
69
|
}
|
|
83
|
-
|
|
84
|
-
resolveSupportedFetchStyleRealtimeCapability(this.adapter
|
|
70
|
+
assertNoFetchStyleServerBackedGatewayOptIn(descriptors, 'bun');
|
|
71
|
+
resolveSupportedFetchStyleRealtimeCapability(this.adapter, {
|
|
72
|
+
packageSubpath: 'bun',
|
|
73
|
+
platformPackage: '@fluojs/platform-bun',
|
|
74
|
+
runtimeName: 'Bun'
|
|
75
|
+
});
|
|
85
76
|
if (!hasBunWebSocketBindingHost(this.adapter)) {
|
|
86
77
|
throw new Error('Bun WebSocket gateway bootstrap requires the selected adapter to expose Bun websocket binding configuration. Use @fluojs/platform-bun with @fluojs/websockets/bun.');
|
|
87
78
|
}
|
|
88
79
|
const bunAdapter = this.adapter;
|
|
89
80
|
bunAdapter.configureWebSocketBinding(this.createBinding(descriptors));
|
|
90
81
|
}
|
|
91
|
-
assertNoServerBackedGatewayOptIn(descriptors) {
|
|
92
|
-
const descriptor = descriptors.find(entry => entry.serverBacked !== undefined);
|
|
93
|
-
if (!descriptor) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
throw new Error(`@WebSocketGateway({ serverBacked }) is not supported on @fluojs/websockets/bun. Gateway path ${descriptor.path} must use the default fetch-style request-upgrade host instead.`);
|
|
97
|
-
}
|
|
98
82
|
async onApplicationShutdown() {
|
|
99
83
|
await this.shutdown();
|
|
100
84
|
}
|
package/dist/bun/bun-types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions } from '../types.js';
|
|
1
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions, WebSocketUpgradeContext, WebSocketUpgradeGuard as SharedWebSocketUpgradeGuard, WebSocketUpgradeRejection } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Defines the bun web socket message type.
|
|
4
4
|
*/
|
|
@@ -78,8 +78,13 @@ export interface WebSocketGatewayContext {
|
|
|
78
78
|
request: Request;
|
|
79
79
|
socket: BunServerWebSocket;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Fetch-style request guard used before Bun websocket upgrades are accepted.
|
|
83
|
+
*/
|
|
84
|
+
export type WebSocketUpgradeGuard = SharedWebSocketUpgradeGuard<Request>;
|
|
85
|
+
export type { WebSocketUpgradeContext, WebSocketUpgradeRejection };
|
|
81
86
|
/**
|
|
82
87
|
* Defines the web socket module options type.
|
|
83
88
|
*/
|
|
84
|
-
export type WebSocketModuleOptions = SharedWebSocketModuleOptions
|
|
89
|
+
export type WebSocketModuleOptions = SharedWebSocketModuleOptions<Request>;
|
|
85
90
|
//# sourceMappingURL=bun-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bun-types.d.ts","sourceRoot":"","sources":["../../src/bun/bun-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"bun-types.d.ts","sourceRoot":"","sources":["../../src/bun/bun-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
3
2
|
import type { HttpApplicationAdapter } from '@fluojs/http';
|
|
3
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
4
4
|
import type { WebSocketRoomService } from '../types.js';
|
|
5
5
|
import type { WebSocketModuleOptions } from './cloudflare-workers-types.js';
|
|
6
6
|
/**
|
|
@@ -22,7 +22,6 @@ export declare class CloudflareWorkersWebSocketGatewayLifecycleService implement
|
|
|
22
22
|
private readonly socketStates;
|
|
23
23
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, adapter: HttpApplicationAdapter, moduleOptions: WebSocketModuleOptions);
|
|
24
24
|
onApplicationBootstrap(): Promise<void>;
|
|
25
|
-
private assertNoServerBackedGatewayOptIn;
|
|
26
25
|
onApplicationShutdown(): Promise<void>;
|
|
27
26
|
onModuleDestroy(): Promise<void>;
|
|
28
27
|
private createBinding;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare-workers-service.d.ts","sourceRoot":"","sources":["../../src/cloudflare-workers/cloudflare-workers-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"cloudflare-workers-service.d.ts","sourceRoot":"","sources":["../../src/cloudflare-workers/cloudflare-workers-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.descrip
|
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
7
|
import { Inject } from '@fluojs/core';
|
|
8
8
|
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
9
|
-
import { dispatchGatewayDisconnect, dispatchGatewayMessage,
|
|
9
|
+
import { assertNoFetchStyleServerBackedGatewayOptIn, discoverGatewayDescriptors, dispatchGatewayDisconnect, dispatchGatewayMessage, isFinitePositiveInteger, normalizeGatewayPath, resolveGatewayInstance, resolveSupportedFetchStyleRealtimeCapability, runGatewayHandlers } from '../internal/shared.js';
|
|
10
10
|
import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
11
11
|
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
12
12
|
const DEFAULT_MAX_WEBSOCKET_CONNECTIONS = 1_000;
|
|
@@ -17,19 +17,6 @@ const WEBSOCKET_OPEN_READY_STATE = 1;
|
|
|
17
17
|
function hasCloudflareWorkerWebSocketBindingHost(adapter) {
|
|
18
18
|
return 'configureWebSocketBinding' in adapter && typeof adapter.configureWebSocketBinding === 'function';
|
|
19
19
|
}
|
|
20
|
-
function resolveSupportedFetchStyleRealtimeCapability(adapter) {
|
|
21
|
-
if (typeof adapter.getRealtimeCapability !== 'function') {
|
|
22
|
-
throw new Error('Cloudflare Workers WebSocket gateway bootstrap requires an HTTP adapter with getRealtimeCapability(). Use @fluojs/platform-cloudflare-workers together with @fluojs/websockets/cloudflare-workers.');
|
|
23
|
-
}
|
|
24
|
-
const capability = adapter.getRealtimeCapability();
|
|
25
|
-
if (capability.kind !== 'fetch-style' || capability.contract !== 'raw-websocket-expansion') {
|
|
26
|
-
throw new Error('Cloudflare Workers WebSocket gateway bootstrap requires a fetch-style raw-websocket-expansion realtime capability from the selected HTTP adapter.');
|
|
27
|
-
}
|
|
28
|
-
if (capability.support !== 'supported') {
|
|
29
|
-
throw new Error(`Cloudflare Workers WebSocket gateway bootstrap requires supported fetch-style websocket hosting. ${capability.reason}`);
|
|
30
|
-
}
|
|
31
|
-
return capability;
|
|
32
|
-
}
|
|
33
20
|
function isWebSocketUpgradeRequest(request) {
|
|
34
21
|
return request.headers.get('upgrade')?.toLowerCase() === 'websocket';
|
|
35
22
|
}
|
|
@@ -84,20 +71,17 @@ class CloudflareWorkersWebSocketGatewayLifecycleService {
|
|
|
84
71
|
if (descriptors.length === 0) {
|
|
85
72
|
return;
|
|
86
73
|
}
|
|
87
|
-
|
|
88
|
-
resolveSupportedFetchStyleRealtimeCapability(this.adapter
|
|
74
|
+
assertNoFetchStyleServerBackedGatewayOptIn(descriptors, 'cloudflare-workers');
|
|
75
|
+
resolveSupportedFetchStyleRealtimeCapability(this.adapter, {
|
|
76
|
+
packageSubpath: 'cloudflare-workers',
|
|
77
|
+
platformPackage: '@fluojs/platform-cloudflare-workers',
|
|
78
|
+
runtimeName: 'Cloudflare Workers'
|
|
79
|
+
});
|
|
89
80
|
if (!hasCloudflareWorkerWebSocketBindingHost(this.adapter)) {
|
|
90
81
|
throw new Error('Cloudflare Workers WebSocket gateway bootstrap requires the selected adapter to expose Cloudflare websocket binding configuration. Use @fluojs/platform-cloudflare-workers with @fluojs/websockets/cloudflare-workers.');
|
|
91
82
|
}
|
|
92
83
|
this.adapter.configureWebSocketBinding(this.createBinding(descriptors));
|
|
93
84
|
}
|
|
94
|
-
assertNoServerBackedGatewayOptIn(descriptors) {
|
|
95
|
-
const descriptor = descriptors.find(entry => entry.serverBacked !== undefined);
|
|
96
|
-
if (!descriptor) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
throw new Error(`@WebSocketGateway({ serverBacked }) is not supported on @fluojs/websockets/cloudflare-workers. Gateway path ${descriptor.path} must use the default fetch-style request-upgrade host instead.`);
|
|
100
|
-
}
|
|
101
85
|
async onApplicationShutdown() {
|
|
102
86
|
await this.shutdown();
|
|
103
87
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions } from '../types.js';
|
|
1
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions, WebSocketUpgradeContext, WebSocketUpgradeGuard as SharedWebSocketUpgradeGuard, WebSocketUpgradeRejection } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Defines the cloudflare worker web socket message type.
|
|
4
4
|
*/
|
|
@@ -53,8 +53,13 @@ export interface WebSocketGatewayContext {
|
|
|
53
53
|
request: Request;
|
|
54
54
|
socket: CloudflareWorkerWebSocket;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Fetch-style request guard used before Cloudflare Workers websocket upgrades are accepted.
|
|
58
|
+
*/
|
|
59
|
+
export type WebSocketUpgradeGuard = SharedWebSocketUpgradeGuard<Request>;
|
|
60
|
+
export type { WebSocketUpgradeContext, WebSocketUpgradeRejection };
|
|
56
61
|
/**
|
|
57
62
|
* Defines the web socket module options type.
|
|
58
63
|
*/
|
|
59
|
-
export type WebSocketModuleOptions = SharedWebSocketModuleOptions
|
|
64
|
+
export type WebSocketModuleOptions = SharedWebSocketModuleOptions<Request>;
|
|
60
65
|
//# sourceMappingURL=cloudflare-workers-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare-workers-types.d.ts","sourceRoot":"","sources":["../../src/cloudflare-workers/cloudflare-workers-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"cloudflare-workers-types.d.ts","sourceRoot":"","sources":["../../src/cloudflare-workers/cloudflare-workers-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,IAAI,4BAA4B,EACtD,uBAAuB,EACvB,qBAAqB,IAAI,2BAA2B,EACpD,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,gCAAgC,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AAE7F;;GAEG;AACH,MAAM,WAAW,yBACf,SAAQ,IAAI,CAAC,SAAS,EAAE,kBAAkB,GAAG,OAAO,GAAG,qBAAqB,GAAG,MAAM,CAAC;IACtF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,MAAM,IAAI,IAAI,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C,CAAC,EAAE,yBAAyB,CAAC;IAC7B,CAAC,EAAE,yBAAyB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACrD,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,yBAAyB,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,sCAAsC,CAAC;CACnE;AAED;;GAEG;AACH,MAAM,WAAW,gCAAgC;IAC/C,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,oCAAoC,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACnG;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,GAAG,SAAS,GAAG,IAAI,CAAC;CACxF;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,IAAI,CACpG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,MAAM,EAAE,yBAAyB,EACjC,OAAO,EAAE,OAAO,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,yBAAyB,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;AAEzE,YAAY,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,4BAA4B,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Container } from '@fluojs/di';
|
|
2
|
-
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
3
2
|
import type { HttpApplicationAdapter } from '@fluojs/http';
|
|
3
|
+
import type { ApplicationLogger, CompiledModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy } from '@fluojs/runtime';
|
|
4
4
|
import type { WebSocketRoomService } from '../types.js';
|
|
5
5
|
import type { WebSocketModuleOptions } from './deno-types.js';
|
|
6
6
|
/**
|
|
@@ -22,7 +22,6 @@ export declare class DenoWebSocketGatewayLifecycleService implements OnApplicati
|
|
|
22
22
|
private readonly socketStates;
|
|
23
23
|
constructor(runtimeContainer: Container, compiledModules: readonly CompiledModule[], logger: ApplicationLogger, adapter: HttpApplicationAdapter, moduleOptions: WebSocketModuleOptions);
|
|
24
24
|
onApplicationBootstrap(): Promise<void>;
|
|
25
|
-
private assertNoServerBackedGatewayOptIn;
|
|
26
25
|
onApplicationShutdown(): Promise<void>;
|
|
27
26
|
onModuleDestroy(): Promise<void>;
|
|
28
27
|
private createBinding;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deno-service.d.ts","sourceRoot":"","sources":["../../src/deno/deno-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"deno-service.d.ts","sourceRoot":"","sources":["../../src/deno/deno-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAgBzI,OAAO,KAAK,EAA8B,oBAAoB,EAA6B,MAAM,aAAa,CAAC;AAC/G,OAAO,KAAK,EAKV,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAgFzB;;GAEG;AACH,qBACa,oCACX,YAAW,sBAAsB,EAAE,qBAAqB,EAAE,eAAe,EAAE,oBAAoB;IAY7F,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAdhC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAA4B;IACrE,OAAO,CAAC,0BAA0B,CAAK;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IACzE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkC;IAC9D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA6C;gBAGvD,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,sBAAsB,EAC/B,aAAa,EAAE,sBAAsB;IAGlD,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC,OAAO,CAAC,aAAa;YAUP,oBAAoB;IAyDlC,OAAO,CAAC,sBAAsB;YAmBhB,sBAAsB;IA8BpC,OAAO,CAAC,4BAA4B;IA8BpC,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,yBAAyB;IASjC,OAAO,CAAC,yBAAyB;IAwCjC,OAAO,CAAC,uBAAuB;IAI/B,OAAO,CAAC,qBAAqB;IAI7B,OAAO,CAAC,4BAA4B;IASpC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,0BAA0B;IASlC,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,qBAAqB;IA0C7B,OAAO,CAAC,sBAAsB;YAyDhB,iBAAiB;YAqBjB,gBAAgB;IAQ9B,OAAO,CAAC,yBAAyB;YAyBnB,yBAAyB;YAczB,kBAAkB;YAgBlB,yBAAyB;YAUzB,8BAA8B;IAqB5C,OAAO,CAAC,YAAY;YAUN,uBAAuB;IA0DrC,OAAO,CAAC,qBAAqB;IAmB7B,OAAO,CAAC,yBAAyB;IAUjC,OAAO,CAAC,8BAA8B;IAItC,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,wBAAwB;YAUlB,QAAQ;YAUR,oBAAoB;IAmBlC,OAAO,CAAC,4BAA4B;YAyBtB,6BAA6B;YA4C7B,kBAAkB;YAoBlB,sBAAsB;IAkDpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAmB9C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAc/C,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IA4BjE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;IAU/C,OAAO,CAAC,gBAAgB;CAqBzB"}
|
|
@@ -6,7 +6,7 @@ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.descrip
|
|
|
6
6
|
function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
|
|
7
7
|
import { Inject } from '@fluojs/core';
|
|
8
8
|
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
9
|
-
import { dispatchGatewayDisconnect, dispatchGatewayMessage,
|
|
9
|
+
import { assertNoFetchStyleServerBackedGatewayOptIn, discoverGatewayDescriptors, dispatchGatewayDisconnect, dispatchGatewayMessage, isFinitePositiveInteger, normalizeGatewayPath, resolveGatewayInstance, resolveSupportedFetchStyleRealtimeCapability, runGatewayHandlers } from '../internal/shared.js';
|
|
10
10
|
import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
11
11
|
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
12
12
|
const DEFAULT_MAX_WEBSOCKET_CONNECTIONS = 1_000;
|
|
@@ -17,19 +17,6 @@ const WEBSOCKET_OPEN_READY_STATE = 1;
|
|
|
17
17
|
function hasDenoWebSocketBindingHost(adapter) {
|
|
18
18
|
return 'configureWebSocketBinding' in adapter && typeof adapter.configureWebSocketBinding === 'function';
|
|
19
19
|
}
|
|
20
|
-
function resolveSupportedFetchStyleRealtimeCapability(adapter) {
|
|
21
|
-
if (typeof adapter.getRealtimeCapability !== 'function') {
|
|
22
|
-
throw new Error('Deno WebSocket gateway bootstrap requires an HTTP adapter with getRealtimeCapability(). Use @fluojs/platform-deno together with @fluojs/websockets/deno.');
|
|
23
|
-
}
|
|
24
|
-
const capability = adapter.getRealtimeCapability();
|
|
25
|
-
if (capability.kind !== 'fetch-style' || capability.contract !== 'raw-websocket-expansion') {
|
|
26
|
-
throw new Error('Deno WebSocket gateway bootstrap requires a fetch-style raw-websocket-expansion realtime capability from the selected HTTP adapter.');
|
|
27
|
-
}
|
|
28
|
-
if (capability.support !== 'supported') {
|
|
29
|
-
throw new Error(`Deno WebSocket gateway bootstrap requires supported fetch-style websocket hosting. ${capability.reason}`);
|
|
30
|
-
}
|
|
31
|
-
return capability;
|
|
32
|
-
}
|
|
33
20
|
function isWebSocketUpgradeRequest(request) {
|
|
34
21
|
return request.headers.get('upgrade')?.toLowerCase() === 'websocket';
|
|
35
22
|
}
|
|
@@ -91,20 +78,17 @@ class DenoWebSocketGatewayLifecycleService {
|
|
|
91
78
|
if (descriptors.length === 0) {
|
|
92
79
|
return;
|
|
93
80
|
}
|
|
94
|
-
|
|
95
|
-
resolveSupportedFetchStyleRealtimeCapability(this.adapter
|
|
81
|
+
assertNoFetchStyleServerBackedGatewayOptIn(descriptors, 'deno');
|
|
82
|
+
resolveSupportedFetchStyleRealtimeCapability(this.adapter, {
|
|
83
|
+
packageSubpath: 'deno',
|
|
84
|
+
platformPackage: '@fluojs/platform-deno',
|
|
85
|
+
runtimeName: 'Deno'
|
|
86
|
+
});
|
|
96
87
|
if (!hasDenoWebSocketBindingHost(this.adapter)) {
|
|
97
88
|
throw new Error('Deno WebSocket gateway bootstrap requires the selected adapter to expose Deno websocket binding configuration. Use @fluojs/platform-deno with @fluojs/websockets/deno.');
|
|
98
89
|
}
|
|
99
90
|
this.adapter.configureWebSocketBinding(this.createBinding(descriptors));
|
|
100
91
|
}
|
|
101
|
-
assertNoServerBackedGatewayOptIn(descriptors) {
|
|
102
|
-
const descriptor = descriptors.find(entry => entry.serverBacked !== undefined);
|
|
103
|
-
if (!descriptor) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
throw new Error(`@WebSocketGateway({ serverBacked }) is not supported on @fluojs/websockets/deno. Gateway path ${descriptor.path} must use the default fetch-style request-upgrade host instead.`);
|
|
107
|
-
}
|
|
108
92
|
async onApplicationShutdown() {
|
|
109
93
|
await this.shutdown();
|
|
110
94
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions } from '../types.js';
|
|
1
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions, WebSocketUpgradeContext, WebSocketUpgradeGuard as SharedWebSocketUpgradeGuard, WebSocketUpgradeRejection } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Defines the Deno websocket inbound message contract.
|
|
4
4
|
*
|
|
@@ -50,8 +50,13 @@ export interface WebSocketGatewayContext {
|
|
|
50
50
|
request: Request;
|
|
51
51
|
socket: DenoServerWebSocket;
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Fetch-style request guard used before Deno websocket upgrades are accepted.
|
|
55
|
+
*/
|
|
56
|
+
export type WebSocketUpgradeGuard = SharedWebSocketUpgradeGuard<Request>;
|
|
57
|
+
export type { WebSocketUpgradeContext, WebSocketUpgradeRejection };
|
|
53
58
|
/**
|
|
54
59
|
* Defines the web socket module options type.
|
|
55
60
|
*/
|
|
56
|
-
export type WebSocketModuleOptions = SharedWebSocketModuleOptions
|
|
61
|
+
export type WebSocketModuleOptions = SharedWebSocketModuleOptions<Request>;
|
|
57
62
|
//# sourceMappingURL=deno-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deno-types.d.ts","sourceRoot":"","sources":["../../src/deno/deno-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"deno-types.d.ts","sourceRoot":"","sources":["../../src/deno/deno-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,IAAI,4BAA4B,EACtD,uBAAuB,EACvB,qBAAqB,IAAI,2BAA2B,EACpD,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,GAAG,MAAM,CAAC;AAEjF;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAAC,SAAS,EAAE,kBAAkB,GAAG,OAAO,GAAG,qBAAqB,GAAG,MAAM,CAAC;IACzH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IACnG,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IACjG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAC;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IAC7F,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,wBAAwB,CAAC,OAAO,CAAC,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CAChG;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB,CAAC,OAAO,SAAS,mBAAmB,GAAG,mBAAmB;IACjG,yBAAyB,CAAC,OAAO,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CACrF;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,IAAI,CACpG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,OAAO,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;AAEzE,YAAY,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,4BAA4B,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Token } from '@fluojs/core';
|
|
2
2
|
import type { Container } from '@fluojs/di';
|
|
3
|
+
import type { FetchStyleHttpAdapterRealtimeCapability, HttpApplicationAdapter } from '@fluojs/http';
|
|
3
4
|
import type { ApplicationLogger, CompiledModule } from '@fluojs/runtime';
|
|
4
5
|
import type { WebSocketGatewayDescriptor, WebSocketGatewayHandlerDescriptor } from '../types.js';
|
|
5
6
|
/**
|
|
@@ -29,6 +30,12 @@ export type ParsedWebSocketMessage = {
|
|
|
29
30
|
* Defines the shared web socket incoming message type.
|
|
30
31
|
*/
|
|
31
32
|
export type SharedWebSocketIncomingMessage = ArrayBuffer | ArrayBufferView | Uint8Array[] | string;
|
|
33
|
+
/** Runtime metadata used to validate fetch-style websocket adapter boundaries. */
|
|
34
|
+
export interface FetchStyleRealtimeBoundaryOptions {
|
|
35
|
+
packageSubpath: string;
|
|
36
|
+
platformPackage: string;
|
|
37
|
+
runtimeName: string;
|
|
38
|
+
}
|
|
32
39
|
/**
|
|
33
40
|
* Is finite positive integer.
|
|
34
41
|
*
|
|
@@ -43,6 +50,21 @@ export declare function isFinitePositiveInteger(value: unknown): value is number
|
|
|
43
50
|
* @returns The normalize gateway path result.
|
|
44
51
|
*/
|
|
45
52
|
export declare function normalizeGatewayPath(path: string): string;
|
|
53
|
+
/**
|
|
54
|
+
* Ensures a fetch-style websocket module is paired with the matching HTTP platform adapter capability.
|
|
55
|
+
*
|
|
56
|
+
* @param adapter The HTTP adapter selected by the application runtime.
|
|
57
|
+
* @param options Runtime-specific package names used in actionable diagnostics.
|
|
58
|
+
* @returns The supported fetch-style realtime capability exposed by the adapter.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolveSupportedFetchStyleRealtimeCapability(adapter: HttpApplicationAdapter, options: FetchStyleRealtimeBoundaryOptions): FetchStyleHttpAdapterRealtimeCapability;
|
|
61
|
+
/**
|
|
62
|
+
* Rejects server-backed gateway opt-in on fetch-style websocket runtime modules.
|
|
63
|
+
*
|
|
64
|
+
* @param descriptors Discovered gateway descriptors for the application.
|
|
65
|
+
* @param packageSubpath Runtime subpath used in diagnostics.
|
|
66
|
+
*/
|
|
67
|
+
export declare function assertNoFetchStyleServerBackedGatewayOptIn(descriptors: readonly WebSocketGatewayDescriptor[], packageSubpath: string): void;
|
|
46
68
|
/**
|
|
47
69
|
* Parse incoming message.
|
|
48
70
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/internal/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/internal/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAuB,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,uCAAuC,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGzE,OAAO,KAAK,EACV,0BAA0B,EAC1B,iCAAiC,EAClC,MAAM,aAAa,CAAC;AAIrB;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,UAAU,EAAE,QAAQ,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;CACd;AAQD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,0BAA0B,CAAC;IACvC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GACtC,WAAW,GACX,eAAe,GACf,UAAU,EAAE,GACZ,MAAM,CAAC;AAEX,kFAAkF;AAClF,MAAM,WAAW,iCAAiC;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;;;;GAMG;AACH,wBAAgB,4CAA4C,CAC1D,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,iCAAiC,GACzC,uCAAuC,CAsBzC;AAED;;;;;GAKG;AACH,wBAAgB,0CAA0C,CACxD,WAAW,EAAE,SAAS,0BAA0B,EAAE,EAClD,cAAc,EAAE,MAAM,GACrB,IAAI,CAUN;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,8BAA8B,GAAG,sBAAsB,CA4CjG;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,GACpB,0BAA0B,EAAE,CA4B9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,gBAAgB,EAAE,SAAS,EAC3B,UAAU,EAAE,0BAA0B,EACtC,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAW9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,QAAQ,EAC5D,QAAQ,EAAE,SAAS,uBAAuB,EAAE,EAC5C,MAAM,EAAE,OAAO,EACf,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,8BAA8B,EACpC,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAkBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EACrD,QAAQ,EAAE,SAAS,uBAAuB,EAAE,EAC5C,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,OAAO,EACjB,UAAU,EAAE,0BAA0B,EACtC,IAAI,EAAE,iCAAiC,CAAC,MAAM,CAAC,EAC/C,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAMf"}
|
package/dist/internal/shared.js
CHANGED
|
@@ -18,6 +18,8 @@ const textDecoder = new TextDecoder();
|
|
|
18
18
|
* Defines the shared web socket incoming message type.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
/** Runtime metadata used to validate fetch-style websocket adapter boundaries. */
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Is finite positive integer.
|
|
23
25
|
*
|
|
@@ -42,6 +44,41 @@ export function normalizeGatewayPath(path) {
|
|
|
42
44
|
return normalized === '' ? '/' : normalized;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Ensures a fetch-style websocket module is paired with the matching HTTP platform adapter capability.
|
|
49
|
+
*
|
|
50
|
+
* @param adapter The HTTP adapter selected by the application runtime.
|
|
51
|
+
* @param options Runtime-specific package names used in actionable diagnostics.
|
|
52
|
+
* @returns The supported fetch-style realtime capability exposed by the adapter.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveSupportedFetchStyleRealtimeCapability(adapter, options) {
|
|
55
|
+
if (typeof adapter.getRealtimeCapability !== 'function') {
|
|
56
|
+
throw new Error(`${options.runtimeName} WebSocket gateway bootstrap requires an HTTP adapter with getRealtimeCapability(). Use ${options.platformPackage} together with @fluojs/websockets/${options.packageSubpath}.`);
|
|
57
|
+
}
|
|
58
|
+
const capability = adapter.getRealtimeCapability();
|
|
59
|
+
if (capability.kind !== 'fetch-style' || capability.contract !== 'raw-websocket-expansion') {
|
|
60
|
+
throw new Error(`${options.runtimeName} WebSocket gateway bootstrap requires a fetch-style raw-websocket-expansion realtime capability from the selected HTTP adapter.`);
|
|
61
|
+
}
|
|
62
|
+
if (capability.support !== 'supported') {
|
|
63
|
+
throw new Error(`${options.runtimeName} WebSocket gateway bootstrap requires supported fetch-style websocket hosting. ${capability.reason}`);
|
|
64
|
+
}
|
|
65
|
+
return capability;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Rejects server-backed gateway opt-in on fetch-style websocket runtime modules.
|
|
70
|
+
*
|
|
71
|
+
* @param descriptors Discovered gateway descriptors for the application.
|
|
72
|
+
* @param packageSubpath Runtime subpath used in diagnostics.
|
|
73
|
+
*/
|
|
74
|
+
export function assertNoFetchStyleServerBackedGatewayOptIn(descriptors, packageSubpath) {
|
|
75
|
+
const descriptor = descriptors.find(entry => entry.serverBacked !== undefined);
|
|
76
|
+
if (!descriptor) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
throw new Error(`@WebSocketGateway({ serverBacked }) is not supported on @fluojs/websockets/${packageSubpath}. Gateway path ${descriptor.path} must use the default fetch-style request-upgrade host instead.`);
|
|
80
|
+
}
|
|
81
|
+
|
|
45
82
|
/**
|
|
46
83
|
* Parse incoming message.
|
|
47
84
|
*
|
|
@@ -152,8 +189,14 @@ export async function dispatchGatewayMessage(resolved, socket, request, data, lo
|
|
|
152
189
|
descriptor,
|
|
153
190
|
instance
|
|
154
191
|
} of resolved) {
|
|
155
|
-
|
|
156
|
-
|
|
192
|
+
for (const handler of descriptor.wildcardMessageHandlers) {
|
|
193
|
+
await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request], logger, loggerContext);
|
|
194
|
+
}
|
|
195
|
+
if (parsed.event === undefined) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const eventHandlers = descriptor.messageHandlersByEvent.get(parsed.event) ?? [];
|
|
199
|
+
for (const handler of eventHandlers) {
|
|
157
200
|
await invokeGatewayMethod(instance, descriptor, handler, [parsed.payload, socket, request], logger, loggerContext);
|
|
158
201
|
}
|
|
159
202
|
}
|
|
@@ -192,7 +235,7 @@ export async function dispatchGatewayDisconnect(resolved, socket, code, reason,
|
|
|
192
235
|
* @returns The run gateway handlers result.
|
|
193
236
|
*/
|
|
194
237
|
export async function runGatewayHandlers(instance, descriptor, type, args, logger, loggerContext) {
|
|
195
|
-
const handlers = descriptor.
|
|
238
|
+
const handlers = type === 'connect' ? descriptor.connectHandlers : descriptor.disconnectHandlers;
|
|
196
239
|
for (const handler of handlers) {
|
|
197
240
|
await invokeGatewayMethod(instance, descriptor, handler, args, logger, loggerContext);
|
|
198
241
|
}
|
|
@@ -247,13 +290,19 @@ function createGatewayDescriptor(candidate, path) {
|
|
|
247
290
|
if (!gatewayMetadata) {
|
|
248
291
|
throw new Error(`Missing websocket gateway metadata for ${candidate.targetType.name}.`);
|
|
249
292
|
}
|
|
293
|
+
const handlers = getWebSocketHandlerMetadataEntries(candidate.targetType.prototype).map(entry => ({
|
|
294
|
+
event: entry.metadata.event,
|
|
295
|
+
methodKey: entry.propertyKey,
|
|
296
|
+
methodName: methodKeyToName(entry.propertyKey),
|
|
297
|
+
type: entry.metadata.type
|
|
298
|
+
}));
|
|
299
|
+
const handlerIndex = createGatewayHandlerIndex(handlers);
|
|
250
300
|
return {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
})),
|
|
301
|
+
connectHandlers: handlerIndex.connectHandlers,
|
|
302
|
+
disconnectHandlers: handlerIndex.disconnectHandlers,
|
|
303
|
+
handlers,
|
|
304
|
+
messageHandlersByEvent: handlerIndex.messageHandlersByEvent,
|
|
305
|
+
wildcardMessageHandlers: handlerIndex.wildcardMessageHandlers,
|
|
257
306
|
moduleName: candidate.moduleName,
|
|
258
307
|
path: normalizeGatewayPath(path),
|
|
259
308
|
serverBacked: gatewayMetadata.serverBacked ? {
|
|
@@ -263,6 +312,35 @@ function createGatewayDescriptor(candidate, path) {
|
|
|
263
312
|
token: candidate.token
|
|
264
313
|
};
|
|
265
314
|
}
|
|
315
|
+
function createGatewayHandlerIndex(handlers) {
|
|
316
|
+
const connectHandlers = [];
|
|
317
|
+
const disconnectHandlers = [];
|
|
318
|
+
const messageHandlersByEvent = new Map();
|
|
319
|
+
const wildcardMessageHandlers = [];
|
|
320
|
+
for (const handler of handlers) {
|
|
321
|
+
if (handler.type === 'connect') {
|
|
322
|
+
connectHandlers.push(handler);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
if (handler.type === 'disconnect') {
|
|
326
|
+
disconnectHandlers.push(handler);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (handler.event === undefined) {
|
|
330
|
+
wildcardMessageHandlers.push(handler);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const eventHandlers = messageHandlersByEvent.get(handler.event) ?? [];
|
|
334
|
+
eventHandlers.push(handler);
|
|
335
|
+
messageHandlersByEvent.set(handler.event, eventHandlers);
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
connectHandlers,
|
|
339
|
+
disconnectHandlers,
|
|
340
|
+
messageHandlersByEvent,
|
|
341
|
+
wildcardMessageHandlers
|
|
342
|
+
};
|
|
343
|
+
}
|
|
266
344
|
function scopeFromProvider(provider) {
|
|
267
345
|
if (typeof provider === 'function') {
|
|
268
346
|
return getClassDiMetadata(provider)?.scope ?? 'singleton';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-service.d.ts","sourceRoot":"","sources":["../../src/node/node-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"node-service.d.ts","sourceRoot":"","sources":["../../src/node/node-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -53,6 +53,12 @@ function resolveMessageByteLength(data) {
|
|
|
53
53
|
}
|
|
54
54
|
return data.byteLength;
|
|
55
55
|
}
|
|
56
|
+
function resolveBoundGatewayPort(address, fallbackPort) {
|
|
57
|
+
if (!address || typeof address === 'string') {
|
|
58
|
+
return fallbackPort;
|
|
59
|
+
}
|
|
60
|
+
return address.port;
|
|
61
|
+
}
|
|
56
62
|
const DEFAULT_WEBSOCKET_SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
57
63
|
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
58
64
|
const DEFAULT_MAX_BUFFERED_AMOUNT_BYTES = 1_048_576;
|
|
@@ -208,10 +214,10 @@ class NodeWebSocketGatewayLifecycleService {
|
|
|
208
214
|
const server = createOwnedGatewayServer();
|
|
209
215
|
const listener = this.createUpgradeListener(server, group.attachmentsByPath);
|
|
210
216
|
server.on('upgrade', listener);
|
|
211
|
-
await this.listenOwnedGatewayServer(server, group.target.port);
|
|
217
|
+
const port = await this.listenOwnedGatewayServer(server, group.target.port);
|
|
212
218
|
this.ownedUpgradeServers.push({
|
|
213
219
|
listener,
|
|
214
|
-
port
|
|
220
|
+
port,
|
|
215
221
|
server
|
|
216
222
|
});
|
|
217
223
|
}
|
|
@@ -263,15 +269,16 @@ class NodeWebSocketGatewayLifecycleService {
|
|
|
263
269
|
};
|
|
264
270
|
}
|
|
265
271
|
const port = this.resolveServerBackedPort(descriptor.path, serverBacked);
|
|
272
|
+
const key = port === 0 ? `owned-server:ephemeral:${descriptor.path}` : `owned-server:${String(port)}`;
|
|
266
273
|
return {
|
|
267
|
-
key
|
|
274
|
+
key,
|
|
268
275
|
kind: 'owned-server',
|
|
269
276
|
port
|
|
270
277
|
};
|
|
271
278
|
}
|
|
272
279
|
resolveServerBackedPort(path, options) {
|
|
273
|
-
if (!isFinitePositiveInteger(options.port)) {
|
|
274
|
-
throw new Error(`WebSocket gateway serverBacked.port for path ${path} must be a finite positive integer.`);
|
|
280
|
+
if (options.port !== 0 && !isFinitePositiveInteger(options.port)) {
|
|
281
|
+
throw new Error(`WebSocket gateway serverBacked.port for path ${path} must be 0 or a finite positive integer.`);
|
|
275
282
|
}
|
|
276
283
|
return options.port;
|
|
277
284
|
}
|
|
@@ -833,18 +840,22 @@ class NodeWebSocketGatewayLifecycleService {
|
|
|
833
840
|
httpServer.once('error', onError);
|
|
834
841
|
server.listen(port, () => {
|
|
835
842
|
httpServer.off('error', onError);
|
|
836
|
-
resolve();
|
|
843
|
+
resolve(resolveBoundGatewayPort(httpServer.address(), port));
|
|
837
844
|
});
|
|
838
845
|
});
|
|
839
846
|
}
|
|
840
847
|
async closeGatewayAttachments(attachments, shutdownTimeoutMs) {
|
|
848
|
+
if (attachments.length === 0) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
const states = [...this.socketStates.values()];
|
|
841
852
|
await Promise.all(attachments.map(async attachment => {
|
|
842
|
-
|
|
853
|
+
this.closeAttachmentClients(attachment);
|
|
843
854
|
await this.closeGatewayAttachment(attachment, shutdownTimeoutMs);
|
|
844
855
|
}));
|
|
856
|
+
await this.awaitHandlerQueueDrain(states, shutdownTimeoutMs);
|
|
845
857
|
}
|
|
846
|
-
|
|
847
|
-
const states = [...this.socketStates.values()];
|
|
858
|
+
closeAttachmentClients(attachment) {
|
|
848
859
|
for (const client of attachment.server.clients) {
|
|
849
860
|
if (client.readyState === WebSocket.OPEN) {
|
|
850
861
|
client.close(1001, 'Server shutting down');
|
|
@@ -852,7 +863,6 @@ class NodeWebSocketGatewayLifecycleService {
|
|
|
852
863
|
client.terminate();
|
|
853
864
|
}
|
|
854
865
|
}
|
|
855
|
-
await this.awaitHandlerQueueDrain(states, timeoutMs);
|
|
856
866
|
}
|
|
857
867
|
async awaitHandlerQueueDrain(states, timeoutMs) {
|
|
858
868
|
if (states.length === 0) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage } from 'node:http';
|
|
2
2
|
import type { WebSocket } from 'ws';
|
|
3
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions, WebSocketUpgradeContext, WebSocketUpgradeGuard as SharedWebSocketUpgradeGuard, WebSocketUpgradeRejection } from '../types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Strongly typed message handler signature for the Node websocket runtime.
|
|
5
6
|
*/
|
|
@@ -11,71 +12,13 @@ export interface WebSocketGatewayContext {
|
|
|
11
12
|
request: IncomingMessage;
|
|
12
13
|
socket: WebSocket;
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
-
* Structured rejection returned by a pre-upgrade websocket guard.
|
|
16
|
-
*/
|
|
17
|
-
export interface WebSocketUpgradeRejection {
|
|
18
|
-
/** Optional plaintext response body sent with the rejection. */
|
|
19
|
-
body?: string;
|
|
20
|
-
/** Optional HTTP headers added to the rejection response. */
|
|
21
|
-
headers?: Record<string, string>;
|
|
22
|
-
/** HTTP status code returned instead of completing the websocket upgrade. */
|
|
23
|
-
status: number;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Runtime context passed to pre-upgrade websocket guards.
|
|
27
|
-
*/
|
|
28
|
-
export interface WebSocketUpgradeContext {
|
|
29
|
-
/** Current number of open websocket connections tracked by the lifecycle service. */
|
|
30
|
-
activeConnectionCount: number;
|
|
31
|
-
/** Normalized gateway path targeted by the upgrade request. */
|
|
32
|
-
path: string;
|
|
33
|
-
}
|
|
15
|
+
export type { WebSocketUpgradeContext, WebSocketUpgradeRejection };
|
|
34
16
|
/**
|
|
35
17
|
* Hook that can allow or reject a websocket upgrade before the adapter accepts it.
|
|
36
18
|
*/
|
|
37
|
-
export type WebSocketUpgradeGuard =
|
|
19
|
+
export type WebSocketUpgradeGuard = SharedWebSocketUpgradeGuard<IncomingMessage | Request>;
|
|
38
20
|
/**
|
|
39
21
|
* Runtime options shared by the Node websocket lifecycle service.
|
|
40
22
|
*/
|
|
41
|
-
export
|
|
42
|
-
/**
|
|
43
|
-
* Limits that bound connection count and inbound payload size across runtime adapters.
|
|
44
|
-
*/
|
|
45
|
-
limits?: {
|
|
46
|
-
/**
|
|
47
|
-
* Maximum number of concurrently tracked websocket connections before new upgrades are rejected.
|
|
48
|
-
*/
|
|
49
|
-
maxConnections?: number;
|
|
50
|
-
/**
|
|
51
|
-
* Maximum inbound payload size in bytes before the connection is rejected or closed.
|
|
52
|
-
*/
|
|
53
|
-
maxPayloadBytes?: number;
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* Upgrade-time controls that run before the adapter completes the websocket handshake.
|
|
57
|
-
*/
|
|
58
|
-
upgrade?: {
|
|
59
|
-
/**
|
|
60
|
-
* Optional guard hook that can deny anonymous or otherwise invalid upgrade requests.
|
|
61
|
-
*/
|
|
62
|
-
guard?: WebSocketUpgradeGuard;
|
|
63
|
-
};
|
|
64
|
-
backpressure?: {
|
|
65
|
-
maxBufferedAmountBytes?: number;
|
|
66
|
-
policy?: 'close' | 'drop';
|
|
67
|
-
};
|
|
68
|
-
buffer?: {
|
|
69
|
-
maxPendingMessagesPerSocket?: number;
|
|
70
|
-
overflowPolicy?: 'close' | 'drop-newest' | 'drop-oldest';
|
|
71
|
-
};
|
|
72
|
-
heartbeat?: {
|
|
73
|
-
enabled?: boolean;
|
|
74
|
-
intervalMs?: number;
|
|
75
|
-
timeoutMs?: number;
|
|
76
|
-
};
|
|
77
|
-
shutdown?: {
|
|
78
|
-
timeoutMs?: number;
|
|
79
|
-
};
|
|
80
|
-
}
|
|
23
|
+
export type WebSocketModuleOptions = SharedWebSocketModuleOptions<IncomingMessage | Request>;
|
|
81
24
|
//# sourceMappingURL=node-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-types.d.ts","sourceRoot":"","sources":["../../src/node/node-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,IAAI,CACpG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,eAAe,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,SAAS,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"node-types.d.ts","sourceRoot":"","sources":["../../src/node/node-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAEpC,OAAO,KAAK,EACV,sBAAsB,IAAI,4BAA4B,EACtD,uBAAuB,EACvB,qBAAqB,IAAI,2BAA2B,EACpD,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,OAAO,IAAI,CACpG,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,eAAe,KACrB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,YAAY,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC;AAE3F;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,4BAA4B,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
1
2
|
import type { MetadataPropertyKey, Token } from '@fluojs/core';
|
|
2
|
-
import type { TypedOnMessageHandler as NodeTypedOnMessageHandler, WebSocketGatewayContext as NodeWebSocketGatewayContext
|
|
3
|
+
import type { TypedOnMessageHandler as NodeTypedOnMessageHandler, WebSocketGatewayContext as NodeWebSocketGatewayContext } from './node/node-types.js';
|
|
3
4
|
/**
|
|
4
5
|
* Event-name-to-payload map used to type `@OnMessage(...)` handlers.
|
|
5
6
|
*/
|
|
@@ -12,7 +13,7 @@ export type TypedOnMessageHandler<TEvents extends WebSocketEventMap, K extends k
|
|
|
12
13
|
* Dedicated listener configuration for runtimes that can host a standalone WebSocket server.
|
|
13
14
|
*/
|
|
14
15
|
export interface WebSocketGatewayServerBackedOptions {
|
|
15
|
-
/** TCP port used by the dedicated listener. */
|
|
16
|
+
/** TCP port used by the dedicated listener. Use `0` to let the host allocate an ephemeral port. */
|
|
16
17
|
port: number;
|
|
17
18
|
}
|
|
18
19
|
/**
|
|
@@ -65,6 +66,14 @@ export interface WebSocketGatewayHandlerDescriptor {
|
|
|
65
66
|
export interface WebSocketGatewayDescriptor {
|
|
66
67
|
/** Ordered handler descriptors discovered on the gateway. */
|
|
67
68
|
handlers: WebSocketGatewayHandlerDescriptor[];
|
|
69
|
+
/** Connect handlers pre-indexed during discovery to avoid lifecycle hot-path filtering. */
|
|
70
|
+
connectHandlers: readonly WebSocketGatewayHandlerDescriptor[];
|
|
71
|
+
/** Disconnect handlers pre-indexed during discovery to avoid lifecycle hot-path filtering. */
|
|
72
|
+
disconnectHandlers: readonly WebSocketGatewayHandlerDescriptor[];
|
|
73
|
+
/** Event-specific message handlers pre-indexed during discovery. */
|
|
74
|
+
messageHandlersByEvent: ReadonlyMap<string, readonly WebSocketGatewayHandlerDescriptor[]>;
|
|
75
|
+
/** Message handlers without an event filter, invoked for every inbound message. */
|
|
76
|
+
wildcardMessageHandlers: readonly WebSocketGatewayHandlerDescriptor[];
|
|
68
77
|
/** Module name that contributed this gateway. */
|
|
69
78
|
moduleName: string;
|
|
70
79
|
/** Normalized upgrade path handled by the gateway. */
|
|
@@ -83,15 +92,29 @@ export type WebSocketGatewayContext = NodeWebSocketGatewayContext;
|
|
|
83
92
|
/**
|
|
84
93
|
* Upgrade-time context shared with pre-upgrade websocket guards.
|
|
85
94
|
*/
|
|
86
|
-
export
|
|
95
|
+
export interface WebSocketUpgradeContext {
|
|
96
|
+
/** Current number of open websocket connections tracked by the lifecycle service. */
|
|
97
|
+
activeConnectionCount: number;
|
|
98
|
+
/** Normalized gateway path targeted by the upgrade request. */
|
|
99
|
+
path: string;
|
|
100
|
+
}
|
|
87
101
|
/**
|
|
88
102
|
* Structured rejection returned by a pre-upgrade websocket guard.
|
|
89
103
|
*/
|
|
90
|
-
export
|
|
104
|
+
export interface WebSocketUpgradeRejection {
|
|
105
|
+
/** Optional plaintext response body sent with the rejection. */
|
|
106
|
+
body?: string;
|
|
107
|
+
/** Optional HTTP headers added to the rejection response. */
|
|
108
|
+
headers?: Record<string, string>;
|
|
109
|
+
/** HTTP status code returned instead of completing the websocket upgrade. */
|
|
110
|
+
status: number;
|
|
111
|
+
}
|
|
91
112
|
/**
|
|
92
113
|
* Hook that can allow or reject a websocket upgrade before the adapter accepts it.
|
|
114
|
+
*
|
|
115
|
+
* @typeParam TRequest Request shape surfaced by the selected websocket runtime.
|
|
93
116
|
*/
|
|
94
|
-
export type WebSocketUpgradeGuard =
|
|
117
|
+
export type WebSocketUpgradeGuard<TRequest = Request> = (request: TRequest, context: WebSocketUpgradeContext) => Promise<boolean | WebSocketUpgradeRejection | void> | boolean | WebSocketUpgradeRejection | void;
|
|
95
118
|
/**
|
|
96
119
|
* Room management API shared by WebSocket protocol adapters.
|
|
97
120
|
*/
|
|
@@ -127,7 +150,38 @@ export interface WebSocketRoomService {
|
|
|
127
150
|
getRooms(socketId: string): ReadonlySet<string>;
|
|
128
151
|
}
|
|
129
152
|
/**
|
|
130
|
-
* Runtime-agnostic module options
|
|
153
|
+
* Runtime-agnostic module options shared by websocket lifecycle services.
|
|
154
|
+
*
|
|
155
|
+
* @typeParam TRequest Request shape received by the runtime-specific pre-upgrade guard.
|
|
131
156
|
*/
|
|
132
|
-
export
|
|
157
|
+
export interface WebSocketModuleOptions<TRequest = IncomingMessage | Request> {
|
|
158
|
+
/** Limits that bound connection count and inbound payload size across runtime adapters. */
|
|
159
|
+
limits?: {
|
|
160
|
+
/** Maximum number of concurrently tracked websocket connections before new upgrades are rejected. */
|
|
161
|
+
maxConnections?: number;
|
|
162
|
+
/** Maximum inbound payload size in bytes before the connection is rejected or closed. */
|
|
163
|
+
maxPayloadBytes?: number;
|
|
164
|
+
};
|
|
165
|
+
/** Upgrade-time controls that run before the adapter completes the websocket handshake. */
|
|
166
|
+
upgrade?: {
|
|
167
|
+
/** Optional guard hook that can deny anonymous or otherwise invalid upgrade requests. */
|
|
168
|
+
guard?: WebSocketUpgradeGuard<TRequest>;
|
|
169
|
+
};
|
|
170
|
+
backpressure?: {
|
|
171
|
+
maxBufferedAmountBytes?: number;
|
|
172
|
+
policy?: 'close' | 'drop';
|
|
173
|
+
};
|
|
174
|
+
buffer?: {
|
|
175
|
+
maxPendingMessagesPerSocket?: number;
|
|
176
|
+
overflowPolicy?: 'close' | 'drop-newest' | 'drop-oldest';
|
|
177
|
+
};
|
|
178
|
+
heartbeat?: {
|
|
179
|
+
enabled?: boolean;
|
|
180
|
+
intervalMs?: number;
|
|
181
|
+
timeoutMs?: number;
|
|
182
|
+
};
|
|
183
|
+
shutdown?: {
|
|
184
|
+
timeoutMs?: number;
|
|
185
|
+
};
|
|
186
|
+
}
|
|
133
187
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EACV,qBAAqB,IAAI,yBAAyB,EAClD,uBAAuB,IAAI,2BAA2B,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"realtime",
|
|
10
10
|
"upgrade"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.0.
|
|
12
|
+
"version": "1.0.5",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -70,17 +70,17 @@
|
|
|
70
70
|
"dependencies": {
|
|
71
71
|
"ws": "^8.18.3",
|
|
72
72
|
"@fluojs/core": "^1.0.3",
|
|
73
|
-
"@fluojs/
|
|
74
|
-
"@fluojs/
|
|
75
|
-
"@fluojs/
|
|
73
|
+
"@fluojs/runtime": "^1.1.6",
|
|
74
|
+
"@fluojs/http": "^1.1.0",
|
|
75
|
+
"@fluojs/di": "^1.1.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@types/ws": "^8.18.1",
|
|
79
79
|
"vitest": "^3.2.4",
|
|
80
|
-
"@fluojs/platform-
|
|
81
|
-
"@fluojs/platform-
|
|
82
|
-
"@fluojs/
|
|
83
|
-
"@fluojs/
|
|
80
|
+
"@fluojs/platform-express": "^1.0.5",
|
|
81
|
+
"@fluojs/platform-bun": "^1.0.5",
|
|
82
|
+
"@fluojs/testing": "^1.0.5",
|
|
83
|
+
"@fluojs/platform-fastify": "^1.0.6"
|
|
84
84
|
},
|
|
85
85
|
"scripts": {
|
|
86
86
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|