@fluojs/websockets 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ko.md +133 -0
- package/README.md +133 -0
- package/dist/bun/bun-module.d.ts +15 -0
- package/dist/bun/bun-module.d.ts.map +1 -0
- package/dist/bun/bun-module.js +27 -0
- package/dist/bun/bun-service.d.ts +63 -0
- package/dist/bun/bun-service.d.ts.map +1 -0
- package/dist/bun/bun-service.js +558 -0
- package/dist/bun/bun-types.d.ts +58 -0
- package/dist/bun/bun-types.d.ts.map +1 -0
- package/dist/bun/bun-types.js +1 -0
- package/dist/bun/bun.d.ts +4 -0
- package/dist/bun/bun.d.ts.map +1 -0
- package/dist/bun/bun.js +3 -0
- package/dist/bun.d.ts +2 -0
- package/dist/bun.d.ts.map +1 -0
- package/dist/bun.js +1 -0
- package/dist/cloudflare-workers/cloudflare-workers-module.d.ts +15 -0
- package/dist/cloudflare-workers/cloudflare-workers-module.d.ts.map +1 -0
- package/dist/cloudflare-workers/cloudflare-workers-module.js +27 -0
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts +61 -0
- package/dist/cloudflare-workers/cloudflare-workers-service.d.ts.map +1 -0
- package/dist/cloudflare-workers/cloudflare-workers-service.js +538 -0
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts +30 -0
- package/dist/cloudflare-workers/cloudflare-workers-types.d.ts.map +1 -0
- package/dist/cloudflare-workers/cloudflare-workers-types.js +1 -0
- package/dist/cloudflare-workers/cloudflare-workers.d.ts +4 -0
- package/dist/cloudflare-workers/cloudflare-workers.d.ts.map +1 -0
- package/dist/cloudflare-workers/cloudflare-workers.js +3 -0
- package/dist/cloudflare-workers.d.ts +2 -0
- package/dist/cloudflare-workers.d.ts.map +1 -0
- package/dist/cloudflare-workers.js +1 -0
- package/dist/decorators.d.ts +56 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +115 -0
- package/dist/deno/deno-module.d.ts +15 -0
- package/dist/deno/deno-module.d.ts.map +1 -0
- package/dist/deno/deno-module.js +27 -0
- package/dist/deno/deno-service.d.ts +61 -0
- package/dist/deno/deno-service.d.ts.map +1 -0
- package/dist/deno/deno-service.js +533 -0
- package/dist/deno/deno-types.d.ts +25 -0
- package/dist/deno/deno-types.d.ts.map +1 -0
- package/dist/deno/deno-types.js +1 -0
- package/dist/deno/deno.d.ts +4 -0
- package/dist/deno/deno.d.ts.map +1 -0
- package/dist/deno/deno.js +3 -0
- package/dist/deno.d.ts +2 -0
- package/dist/deno.d.ts.map +1 -0
- package/dist/deno.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/internal/shared.d.ts +28 -0
- package/dist/internal/shared.d.ts.map +1 -0
- package/dist/internal/shared.js +188 -0
- package/dist/metadata.d.ts +13 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +81 -0
- package/dist/module.d.ts +26 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +26 -0
- package/dist/node/node-module.d.ts +15 -0
- package/dist/node/node-module.d.ts.map +1 -0
- package/dist/node/node-module.js +27 -0
- package/dist/node/node-service.d.ts +129 -0
- package/dist/node/node-service.d.ts.map +1 -0
- package/dist/node/node-service.js +892 -0
- package/dist/node/node-types.d.ts +81 -0
- package/dist/node/node-types.d.ts.map +1 -0
- package/dist/node/node-types.js +1 -0
- package/dist/node/node.d.ts +4 -0
- package/dist/node/node.d.ts.map +1 -0
- package/dist/node/node.js +3 -0
- package/dist/node.d.ts +2 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +1 -0
- package/dist/options-token.internal.d.ts +7 -0
- package/dist/options-token.internal.d.ts.map +1 -0
- package/dist/options-token.internal.js +4 -0
- package/dist/service.d.ts +9 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +8 -0
- package/dist/types.d.ts +133 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
let _initClass;
|
|
2
|
+
function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
|
|
3
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
4
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
5
|
+
function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
|
|
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
|
+
import { Inject } from '@fluojs/core';
|
|
8
|
+
import { APPLICATION_LOGGER, COMPILED_MODULES, HTTP_APPLICATION_ADAPTER, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
|
|
9
|
+
import { dispatchGatewayDisconnect, dispatchGatewayMessage, discoverGatewayDescriptors, isFinitePositiveInteger, normalizeGatewayPath, resolveGatewayInstance, runGatewayHandlers } from '../internal/shared.js';
|
|
10
|
+
import { WEBSOCKET_OPTIONS_INTERNAL } from '../options-token.internal.js';
|
|
11
|
+
const DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET = 256;
|
|
12
|
+
const DEFAULT_MAX_WEBSOCKET_CONNECTIONS = 1_000;
|
|
13
|
+
const DEFAULT_MAX_WEBSOCKET_PAYLOAD_BYTES = 1_048_576;
|
|
14
|
+
const LIFECYCLE_LOG_CONTEXT = 'WebSocketGatewayLifecycleService';
|
|
15
|
+
function hasBunWebSocketBindingHost(adapter) {
|
|
16
|
+
return 'configureWebSocketBinding' in adapter && typeof adapter.configureWebSocketBinding === 'function';
|
|
17
|
+
}
|
|
18
|
+
function resolveSupportedFetchStyleRealtimeCapability(adapter) {
|
|
19
|
+
if (typeof adapter.getRealtimeCapability !== 'function') {
|
|
20
|
+
throw new Error('Bun WebSocket gateway bootstrap requires an HTTP adapter with getRealtimeCapability(). Use @fluojs/platform-bun together with @fluojs/websockets/bun.');
|
|
21
|
+
}
|
|
22
|
+
const capability = adapter.getRealtimeCapability();
|
|
23
|
+
if (capability.kind !== 'fetch-style' || capability.contract !== 'raw-websocket-expansion') {
|
|
24
|
+
throw new Error('Bun WebSocket gateway bootstrap requires a fetch-style raw-websocket-expansion realtime capability from the selected HTTP adapter.');
|
|
25
|
+
}
|
|
26
|
+
if (capability.support !== 'supported') {
|
|
27
|
+
throw new Error(`Bun WebSocket gateway bootstrap requires supported fetch-style websocket hosting. ${capability.reason}`);
|
|
28
|
+
}
|
|
29
|
+
return capability;
|
|
30
|
+
}
|
|
31
|
+
function isHttpExceptionLike(error) {
|
|
32
|
+
return typeof error === 'object' && error !== null && 'message' in error && 'status' in error;
|
|
33
|
+
}
|
|
34
|
+
function resolveMessageByteLength(message) {
|
|
35
|
+
if (typeof message === 'string') {
|
|
36
|
+
return Buffer.byteLength(message);
|
|
37
|
+
}
|
|
38
|
+
return message.byteLength;
|
|
39
|
+
}
|
|
40
|
+
function isWebSocketUpgradeRequest(request) {
|
|
41
|
+
return request.headers.get('upgrade')?.toLowerCase() === 'websocket';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Boots Bun-backed websocket gateways and manages their room lifecycle state.
|
|
46
|
+
*/
|
|
47
|
+
let _BunWebSocketGatewayL;
|
|
48
|
+
class BunWebSocketGatewayLifecycleService {
|
|
49
|
+
static {
|
|
50
|
+
[_BunWebSocketGatewayL, _initClass] = _applyDecs(this, [Inject(RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER, HTTP_APPLICATION_ADAPTER, WEBSOCKET_OPTIONS_INTERNAL)], []).c;
|
|
51
|
+
}
|
|
52
|
+
pendingUpgradeReservations = 0;
|
|
53
|
+
roomSockets = new Map();
|
|
54
|
+
shutdownPromise;
|
|
55
|
+
socketRegistry = new Map();
|
|
56
|
+
socketRooms = new Map();
|
|
57
|
+
constructor(runtimeContainer, compiledModules, logger, adapter, moduleOptions) {
|
|
58
|
+
this.runtimeContainer = runtimeContainer;
|
|
59
|
+
this.compiledModules = compiledModules;
|
|
60
|
+
this.logger = logger;
|
|
61
|
+
this.adapter = adapter;
|
|
62
|
+
this.moduleOptions = moduleOptions;
|
|
63
|
+
}
|
|
64
|
+
async onApplicationBootstrap() {
|
|
65
|
+
const descriptors = discoverGatewayDescriptors(this.compiledModules, this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
66
|
+
if (descriptors.length === 0) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.assertNoServerBackedGatewayOptIn(descriptors);
|
|
70
|
+
resolveSupportedFetchStyleRealtimeCapability(this.adapter);
|
|
71
|
+
if (!hasBunWebSocketBindingHost(this.adapter)) {
|
|
72
|
+
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.');
|
|
73
|
+
}
|
|
74
|
+
const bunAdapter = this.adapter;
|
|
75
|
+
bunAdapter.configureWebSocketBinding(this.createBinding(descriptors));
|
|
76
|
+
}
|
|
77
|
+
assertNoServerBackedGatewayOptIn(descriptors) {
|
|
78
|
+
const descriptor = descriptors.find(entry => entry.serverBacked !== undefined);
|
|
79
|
+
if (!descriptor) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
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.`);
|
|
83
|
+
}
|
|
84
|
+
async onApplicationShutdown() {
|
|
85
|
+
await this.shutdown();
|
|
86
|
+
}
|
|
87
|
+
async onModuleDestroy() {
|
|
88
|
+
await this.shutdown();
|
|
89
|
+
}
|
|
90
|
+
createBinding(descriptors) {
|
|
91
|
+
const descriptorsByPath = this.groupDescriptorsByPath(descriptors);
|
|
92
|
+
return {
|
|
93
|
+
fetch: (request, server) => this.handleUpgradeRequest(request, server, descriptorsByPath),
|
|
94
|
+
websocket: {
|
|
95
|
+
backpressureLimit: this.resolveBackpressureLimit(),
|
|
96
|
+
close: (socket, code, reason) => {
|
|
97
|
+
this.unregisterSocket(socket.data.state.socketId);
|
|
98
|
+
this.handleSocketClose(socket, code, reason);
|
|
99
|
+
},
|
|
100
|
+
closeOnBackpressureLimit: this.moduleOptions.backpressure?.policy === 'close',
|
|
101
|
+
error: (socket, error) => {
|
|
102
|
+
this.unregisterSocket(socket.data.state.socketId);
|
|
103
|
+
this.logger.error('WebSocket gateway socket emitted an error.', error, LIFECYCLE_LOG_CONTEXT);
|
|
104
|
+
},
|
|
105
|
+
idleTimeout: this.resolveIdleTimeoutSeconds(),
|
|
106
|
+
maxPayloadLength: this.resolveMaxPayloadBytes(),
|
|
107
|
+
message: (socket, message) => {
|
|
108
|
+
this.handleSocketMessage(socket, message);
|
|
109
|
+
},
|
|
110
|
+
open: socket => {
|
|
111
|
+
void this.bindConnectionHandlers(socket).catch(error => {
|
|
112
|
+
this.unregisterSocket(socket.data.state.socketId);
|
|
113
|
+
this.logger.error('WebSocket gateway open lifecycle failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
114
|
+
socket.close(1011, 'Internal server error');
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
sendPings: this.moduleOptions.heartbeat?.enabled !== false
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
groupDescriptorsByPath(descriptors) {
|
|
122
|
+
const descriptorsByPath = new Map();
|
|
123
|
+
for (const descriptor of descriptors) {
|
|
124
|
+
const current = descriptorsByPath.get(descriptor.path);
|
|
125
|
+
if (current) {
|
|
126
|
+
current.push(descriptor);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
descriptorsByPath.set(descriptor.path, [descriptor]);
|
|
130
|
+
}
|
|
131
|
+
return descriptorsByPath;
|
|
132
|
+
}
|
|
133
|
+
async handleUpgradeRequest(request, server, descriptorsByPath) {
|
|
134
|
+
let targetPath;
|
|
135
|
+
try {
|
|
136
|
+
targetPath = normalizeGatewayPath(new URL(request.url).pathname);
|
|
137
|
+
} catch {
|
|
138
|
+
return new Response(null, {
|
|
139
|
+
status: 400
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const descriptors = descriptorsByPath.get(targetPath);
|
|
143
|
+
if (!descriptors) {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
if (!isWebSocketUpgradeRequest(request)) {
|
|
147
|
+
return new Response(null, {
|
|
148
|
+
status: 426
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
const rejection = await this.resolveUpgradeRejection(request, targetPath);
|
|
152
|
+
if (rejection) {
|
|
153
|
+
return new Response(rejection.body ?? null, {
|
|
154
|
+
headers: rejection.headers,
|
|
155
|
+
status: rejection.status
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const state = this.createConnectionHandlerState(request, [...descriptors]);
|
|
159
|
+
let upgraded = false;
|
|
160
|
+
try {
|
|
161
|
+
upgraded = server.upgrade(request, {
|
|
162
|
+
data: {
|
|
163
|
+
state
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
} catch (error) {
|
|
167
|
+
this.releaseUpgradeReservation();
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
if (!upgraded) {
|
|
171
|
+
this.releaseUpgradeReservation();
|
|
172
|
+
return new Response(null, {
|
|
173
|
+
status: 400
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
async bindConnectionHandlers(socket) {
|
|
179
|
+
const {
|
|
180
|
+
state
|
|
181
|
+
} = socket.data;
|
|
182
|
+
this.releaseUpgradeReservation();
|
|
183
|
+
this.socketRegistry.set(state.socketId, socket);
|
|
184
|
+
await this.resolveConnectionGateways(state);
|
|
185
|
+
await this.runConnectHandlers(state, socket);
|
|
186
|
+
await this.finalizeConnectionBinding(state, socket);
|
|
187
|
+
}
|
|
188
|
+
createConnectionHandlerState(request, descriptors) {
|
|
189
|
+
return {
|
|
190
|
+
bufferedDisconnect: undefined,
|
|
191
|
+
bufferedMessages: [],
|
|
192
|
+
bufferedMessagesStartIndex: 0,
|
|
193
|
+
descriptors,
|
|
194
|
+
enqueuedMessageCount: 0,
|
|
195
|
+
handlerQueue: Promise.resolve(),
|
|
196
|
+
handlersReady: false,
|
|
197
|
+
processingMessageQueue: false,
|
|
198
|
+
queuedMessages: [],
|
|
199
|
+
queuedMessagesStartIndex: 0,
|
|
200
|
+
request,
|
|
201
|
+
resolved: [],
|
|
202
|
+
socketId: crypto.randomUUID()
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
getBufferedMessageCount(state) {
|
|
206
|
+
return state.bufferedMessages.length - state.bufferedMessagesStartIndex;
|
|
207
|
+
}
|
|
208
|
+
getQueuedMessageCount(state) {
|
|
209
|
+
return state.queuedMessages.length - state.queuedMessagesStartIndex;
|
|
210
|
+
}
|
|
211
|
+
maybeCompactBufferedMessages(state) {
|
|
212
|
+
if (state.bufferedMessagesStartIndex === 0 || state.bufferedMessagesStartIndex < state.bufferedMessages.length / 2) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
state.bufferedMessages = state.bufferedMessages.slice(state.bufferedMessagesStartIndex);
|
|
216
|
+
state.bufferedMessagesStartIndex = 0;
|
|
217
|
+
}
|
|
218
|
+
clearBufferedMessages(state) {
|
|
219
|
+
state.bufferedMessages = [];
|
|
220
|
+
state.bufferedMessagesStartIndex = 0;
|
|
221
|
+
}
|
|
222
|
+
maybeCompactQueuedMessages(state) {
|
|
223
|
+
if (state.queuedMessagesStartIndex === 0 || state.queuedMessagesStartIndex < state.queuedMessages.length / 2) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
state.queuedMessages = state.queuedMessages.slice(state.queuedMessagesStartIndex);
|
|
227
|
+
state.queuedMessagesStartIndex = 0;
|
|
228
|
+
}
|
|
229
|
+
clearQueuedMessages(state) {
|
|
230
|
+
state.queuedMessages = [];
|
|
231
|
+
state.queuedMessagesStartIndex = 0;
|
|
232
|
+
state.enqueuedMessageCount = 0;
|
|
233
|
+
}
|
|
234
|
+
handleSocketMessage(socket, message) {
|
|
235
|
+
const {
|
|
236
|
+
state
|
|
237
|
+
} = socket.data;
|
|
238
|
+
if (this.closeOversizedPayload(state.socketId, socket, message)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (!state.handlersReady) {
|
|
242
|
+
this.bufferIncomingMessage(state, socket, message);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.enqueueMessageDispatch(state, socket, message);
|
|
246
|
+
}
|
|
247
|
+
handleSocketClose(socket, code, reason) {
|
|
248
|
+
const {
|
|
249
|
+
state
|
|
250
|
+
} = socket.data;
|
|
251
|
+
const disconnectEvent = {
|
|
252
|
+
code,
|
|
253
|
+
reason
|
|
254
|
+
};
|
|
255
|
+
if (!state.handlersReady) {
|
|
256
|
+
state.bufferedDisconnect = disconnectEvent;
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.enqueueDisconnectDispatch(state, socket, disconnectEvent);
|
|
260
|
+
}
|
|
261
|
+
bufferIncomingMessage(state, socket, message) {
|
|
262
|
+
const limit = isFinitePositiveInteger(this.moduleOptions.buffer?.maxPendingMessagesPerSocket) ? this.moduleOptions.buffer.maxPendingMessagesPerSocket : DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET;
|
|
263
|
+
const policy = this.moduleOptions.buffer?.overflowPolicy ?? 'drop-oldest';
|
|
264
|
+
if (this.getBufferedMessageCount(state) < limit) {
|
|
265
|
+
state.bufferedMessages.push(message);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (policy === 'close') {
|
|
269
|
+
socket.close(1013, 'Pending message buffer limit exceeded');
|
|
270
|
+
this.clearBufferedMessages(state);
|
|
271
|
+
this.logger.warn(`WebSocket connection ${state.socketId} exceeded pending message buffer limit (${String(limit)}). Connection closed.`, LIFECYCLE_LOG_CONTEXT);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (policy === 'drop-newest') {
|
|
275
|
+
this.logger.warn(`WebSocket connection ${state.socketId} dropped an incoming message due to pending buffer limit (${String(limit)}).`, LIFECYCLE_LOG_CONTEXT);
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
state.bufferedMessagesStartIndex += 1;
|
|
279
|
+
this.maybeCompactBufferedMessages(state);
|
|
280
|
+
state.bufferedMessages.push(message);
|
|
281
|
+
this.logger.warn(`WebSocket connection ${state.socketId} dropped the oldest pending message due to buffer limit (${String(limit)}).`, LIFECYCLE_LOG_CONTEXT);
|
|
282
|
+
}
|
|
283
|
+
enqueueMessageDispatch(state, socket, message) {
|
|
284
|
+
const limit = isFinitePositiveInteger(this.moduleOptions.buffer?.maxPendingMessagesPerSocket) ? this.moduleOptions.buffer.maxPendingMessagesPerSocket : DEFAULT_MAX_PENDING_MESSAGES_PER_SOCKET;
|
|
285
|
+
const policy = this.moduleOptions.buffer?.overflowPolicy ?? 'drop-oldest';
|
|
286
|
+
if (this.getQueuedMessageCount(state) >= limit) {
|
|
287
|
+
if (policy === 'close') {
|
|
288
|
+
socket.close(1013, 'Ready-state message queue limit exceeded');
|
|
289
|
+
this.clearQueuedMessages(state);
|
|
290
|
+
this.unregisterSocket(state.socketId);
|
|
291
|
+
this.logger.warn(`WebSocket connection ${state.socketId} exceeded ready-state message queue limit (${String(limit)}). Connection closed.`, LIFECYCLE_LOG_CONTEXT);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (policy === 'drop-oldest') {
|
|
295
|
+
state.queuedMessagesStartIndex += 1;
|
|
296
|
+
this.maybeCompactQueuedMessages(state);
|
|
297
|
+
this.logger.warn(`WebSocket connection ${state.socketId} dropped the oldest ready-state message because queue limit (${String(limit)}) was reached.`, LIFECYCLE_LOG_CONTEXT);
|
|
298
|
+
} else {
|
|
299
|
+
this.logger.warn(`WebSocket connection ${state.socketId} dropped a ready-state message because queue limit (${String(limit)}) was reached.`, LIFECYCLE_LOG_CONTEXT);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
state.queuedMessages.push(message);
|
|
304
|
+
state.enqueuedMessageCount = this.getQueuedMessageCount(state);
|
|
305
|
+
if (state.processingMessageQueue) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
state.processingMessageQueue = true;
|
|
309
|
+
state.handlerQueue = this.drainMessageQueue(state, socket).finally(() => {
|
|
310
|
+
state.processingMessageQueue = false;
|
|
311
|
+
state.enqueuedMessageCount = this.getQueuedMessageCount(state);
|
|
312
|
+
}).catch(error => {
|
|
313
|
+
this.logger.error('WebSocket gateway message dispatch failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
async drainMessageQueue(state, socket) {
|
|
317
|
+
while (state.queuedMessagesStartIndex < state.queuedMessages.length) {
|
|
318
|
+
const nextMessage = state.queuedMessages[state.queuedMessagesStartIndex];
|
|
319
|
+
state.queuedMessagesStartIndex += 1;
|
|
320
|
+
state.enqueuedMessageCount = this.getQueuedMessageCount(state);
|
|
321
|
+
if (nextMessage === undefined) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
await dispatchGatewayMessage(state.resolved, socket, state.request, nextMessage, this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
325
|
+
}
|
|
326
|
+
this.clearQueuedMessages(state);
|
|
327
|
+
}
|
|
328
|
+
enqueueDisconnectDispatch(state, socket, disconnectEvent) {
|
|
329
|
+
state.handlerQueue = state.handlerQueue.then(async () => {
|
|
330
|
+
await dispatchGatewayDisconnect(state.resolved, socket, disconnectEvent.code, disconnectEvent.reason, state.socketId, this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
331
|
+
}).catch(error => {
|
|
332
|
+
this.logger.error('WebSocket gateway disconnect dispatch failed.', error, LIFECYCLE_LOG_CONTEXT);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
async resolveConnectionGateways(state) {
|
|
336
|
+
const resolved = [];
|
|
337
|
+
for (const descriptor of state.descriptors) {
|
|
338
|
+
const instance = await resolveGatewayInstance(this.runtimeContainer, descriptor, this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
339
|
+
if (instance !== undefined) {
|
|
340
|
+
resolved.push({
|
|
341
|
+
descriptor,
|
|
342
|
+
instance
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
state.resolved = resolved;
|
|
347
|
+
}
|
|
348
|
+
async runConnectHandlers(state, socket) {
|
|
349
|
+
for (const {
|
|
350
|
+
descriptor,
|
|
351
|
+
instance
|
|
352
|
+
} of state.resolved) {
|
|
353
|
+
await runGatewayHandlers(instance, descriptor, 'connect', [socket, state.request, state.socketId], this.logger, LIFECYCLE_LOG_CONTEXT);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
async finalizeConnectionBinding(state, socket) {
|
|
357
|
+
state.handlersReady = true;
|
|
358
|
+
this.replayBufferedConnectionEvents(state, socket);
|
|
359
|
+
await state.handlerQueue;
|
|
360
|
+
}
|
|
361
|
+
replayBufferedConnectionEvents(state, socket) {
|
|
362
|
+
for (let index = state.bufferedMessagesStartIndex; index < state.bufferedMessages.length; index += 1) {
|
|
363
|
+
const message = state.bufferedMessages[index];
|
|
364
|
+
if (message !== undefined) {
|
|
365
|
+
this.enqueueMessageDispatch(state, socket, message);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (state.bufferedDisconnect) {
|
|
369
|
+
this.enqueueDisconnectDispatch(state, socket, state.bufferedDisconnect);
|
|
370
|
+
state.bufferedDisconnect = undefined;
|
|
371
|
+
}
|
|
372
|
+
this.clearBufferedMessages(state);
|
|
373
|
+
}
|
|
374
|
+
resolveBackpressureLimit() {
|
|
375
|
+
const configured = this.moduleOptions.backpressure?.maxBufferedAmountBytes;
|
|
376
|
+
if (!isFinitePositiveInteger(configured)) {
|
|
377
|
+
return 1_048_576;
|
|
378
|
+
}
|
|
379
|
+
return configured;
|
|
380
|
+
}
|
|
381
|
+
async resolveUpgradeRejection(request, path) {
|
|
382
|
+
if (!this.tryReserveUpgradeSlot()) {
|
|
383
|
+
return {
|
|
384
|
+
body: 'WebSocket connection limit exceeded.',
|
|
385
|
+
status: 429
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
const guard = this.moduleOptions.upgrade?.guard;
|
|
389
|
+
if (!guard) {
|
|
390
|
+
return undefined;
|
|
391
|
+
}
|
|
392
|
+
try {
|
|
393
|
+
const result = await guard(request, {
|
|
394
|
+
activeConnectionCount: this.resolveReservedConnectionCount() - 1,
|
|
395
|
+
path
|
|
396
|
+
});
|
|
397
|
+
if (result === false) {
|
|
398
|
+
this.releaseUpgradeReservation();
|
|
399
|
+
return {
|
|
400
|
+
body: 'WebSocket upgrade rejected.',
|
|
401
|
+
status: 403
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
if (typeof result === 'object' && result !== null && 'status' in result) {
|
|
405
|
+
this.releaseUpgradeReservation();
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
return undefined;
|
|
409
|
+
} catch (error) {
|
|
410
|
+
this.releaseUpgradeReservation();
|
|
411
|
+
if (isHttpExceptionLike(error)) {
|
|
412
|
+
return {
|
|
413
|
+
body: error.message,
|
|
414
|
+
status: error.status
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
closeOversizedPayload(socketId, socket, message) {
|
|
421
|
+
const maxPayloadBytes = this.resolveMaxPayloadBytes();
|
|
422
|
+
if (resolveMessageByteLength(message) <= maxPayloadBytes) {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
socket.close(1009, 'Payload too large');
|
|
426
|
+
this.logger.warn(`WebSocket connection ${socketId} exceeded payload limit (${String(maxPayloadBytes)} bytes). Connection closed.`, LIFECYCLE_LOG_CONTEXT);
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
resolveMaxConnectionCount() {
|
|
430
|
+
const configured = this.moduleOptions.limits?.maxConnections;
|
|
431
|
+
if (!isFinitePositiveInteger(configured)) {
|
|
432
|
+
return DEFAULT_MAX_WEBSOCKET_CONNECTIONS;
|
|
433
|
+
}
|
|
434
|
+
return configured;
|
|
435
|
+
}
|
|
436
|
+
resolveReservedConnectionCount() {
|
|
437
|
+
return this.socketRegistry.size + this.pendingUpgradeReservations;
|
|
438
|
+
}
|
|
439
|
+
tryReserveUpgradeSlot() {
|
|
440
|
+
if (this.resolveReservedConnectionCount() >= this.resolveMaxConnectionCount()) {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
this.pendingUpgradeReservations += 1;
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
releaseUpgradeReservation() {
|
|
447
|
+
if (this.pendingUpgradeReservations > 0) {
|
|
448
|
+
this.pendingUpgradeReservations -= 1;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
resolveMaxPayloadBytes() {
|
|
452
|
+
const configured = this.moduleOptions.limits?.maxPayloadBytes;
|
|
453
|
+
if (!isFinitePositiveInteger(configured)) {
|
|
454
|
+
return DEFAULT_MAX_WEBSOCKET_PAYLOAD_BYTES;
|
|
455
|
+
}
|
|
456
|
+
return configured;
|
|
457
|
+
}
|
|
458
|
+
resolveIdleTimeoutSeconds() {
|
|
459
|
+
if (this.moduleOptions.heartbeat?.enabled === false) {
|
|
460
|
+
return 0;
|
|
461
|
+
}
|
|
462
|
+
const configured = this.moduleOptions.heartbeat?.timeoutMs;
|
|
463
|
+
if (!isFinitePositiveInteger(configured)) {
|
|
464
|
+
return 120;
|
|
465
|
+
}
|
|
466
|
+
return Math.max(1, Math.ceil(configured / 1000));
|
|
467
|
+
}
|
|
468
|
+
async shutdown() {
|
|
469
|
+
if (this.shutdownPromise) {
|
|
470
|
+
await this.shutdownPromise;
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
this.shutdownPromise = this.runShutdownLifecycle();
|
|
474
|
+
await this.shutdownPromise;
|
|
475
|
+
}
|
|
476
|
+
async runShutdownLifecycle() {
|
|
477
|
+
if (hasBunWebSocketBindingHost(this.adapter)) {
|
|
478
|
+
const bunAdapter = this.adapter;
|
|
479
|
+
bunAdapter.configureWebSocketBinding(undefined);
|
|
480
|
+
}
|
|
481
|
+
this.pendingUpgradeReservations = 0;
|
|
482
|
+
this.socketRegistry.clear();
|
|
483
|
+
this.socketRooms.clear();
|
|
484
|
+
this.roomSockets.clear();
|
|
485
|
+
}
|
|
486
|
+
joinRoom(socketId, room) {
|
|
487
|
+
let rooms = this.socketRooms.get(socketId);
|
|
488
|
+
if (!rooms) {
|
|
489
|
+
rooms = new Set();
|
|
490
|
+
this.socketRooms.set(socketId, rooms);
|
|
491
|
+
}
|
|
492
|
+
rooms.add(room);
|
|
493
|
+
let sockets = this.roomSockets.get(room);
|
|
494
|
+
if (!sockets) {
|
|
495
|
+
sockets = new Set();
|
|
496
|
+
this.roomSockets.set(room, sockets);
|
|
497
|
+
}
|
|
498
|
+
sockets.add(socketId);
|
|
499
|
+
}
|
|
500
|
+
leaveRoom(socketId, room) {
|
|
501
|
+
const rooms = this.socketRooms.get(socketId);
|
|
502
|
+
rooms?.delete(room);
|
|
503
|
+
if (rooms && rooms.size === 0) {
|
|
504
|
+
this.socketRooms.delete(socketId);
|
|
505
|
+
}
|
|
506
|
+
const sockets = this.roomSockets.get(room);
|
|
507
|
+
sockets?.delete(socketId);
|
|
508
|
+
if (sockets && sockets.size === 0) {
|
|
509
|
+
this.roomSockets.delete(room);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
broadcastToRoom(room, event, data) {
|
|
513
|
+
const socketIds = this.roomSockets.get(room);
|
|
514
|
+
if (!socketIds) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const message = JSON.stringify({
|
|
518
|
+
data,
|
|
519
|
+
event
|
|
520
|
+
});
|
|
521
|
+
for (const socketId of socketIds) {
|
|
522
|
+
const socket = this.socketRegistry.get(socketId);
|
|
523
|
+
if (!socket || socket.readyState !== 1) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const result = socket.send(message);
|
|
527
|
+
if (result === 0) {
|
|
528
|
+
this.unregisterSocket(socketId);
|
|
529
|
+
this.logger.warn(`WebSocket connection ${socketId} dropped a room broadcast because the socket was unavailable.`, LIFECYCLE_LOG_CONTEXT);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
getRooms(socketId) {
|
|
534
|
+
const rooms = this.socketRooms.get(socketId);
|
|
535
|
+
if (!rooms) {
|
|
536
|
+
return new Set();
|
|
537
|
+
}
|
|
538
|
+
return new Set(rooms);
|
|
539
|
+
}
|
|
540
|
+
unregisterSocket(socketId) {
|
|
541
|
+
this.socketRegistry.delete(socketId);
|
|
542
|
+
const rooms = this.socketRooms.get(socketId);
|
|
543
|
+
if (rooms) {
|
|
544
|
+
for (const room of rooms) {
|
|
545
|
+
const sockets = this.roomSockets.get(room);
|
|
546
|
+
sockets?.delete(socketId);
|
|
547
|
+
if (sockets && sockets.size === 0) {
|
|
548
|
+
this.roomSockets.delete(room);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
this.socketRooms.delete(socketId);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
static {
|
|
555
|
+
_initClass();
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
export { _BunWebSocketGatewayL as BunWebSocketGatewayLifecycleService };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { WebSocketModuleOptions as SharedWebSocketModuleOptions } from '../types.js';
|
|
2
|
+
export type BunWebSocketMessage = string | ArrayBuffer | Uint8Array;
|
|
3
|
+
export interface BunServerWebSocket<TData = unknown> {
|
|
4
|
+
readonly data: TData;
|
|
5
|
+
readonly readyState: number;
|
|
6
|
+
readonly remoteAddress: string;
|
|
7
|
+
readonly subscriptions: string[];
|
|
8
|
+
close(code?: number, reason?: string): void;
|
|
9
|
+
cork(callback: (socket: BunServerWebSocket<TData>) => void): void;
|
|
10
|
+
isSubscribed(topic: string): boolean;
|
|
11
|
+
publish(topic: string, message: BunWebSocketMessage): void;
|
|
12
|
+
send(message: BunWebSocketMessage, compress?: boolean): number;
|
|
13
|
+
subscribe(topic: string): void;
|
|
14
|
+
unsubscribe(topic: string): void;
|
|
15
|
+
}
|
|
16
|
+
export interface BunServerLike {
|
|
17
|
+
fetch?(request: Request): Response | Promise<Response> | undefined | Promise<Response | undefined>;
|
|
18
|
+
hostname?: string;
|
|
19
|
+
port?: number;
|
|
20
|
+
stop(closeActiveConnections?: boolean): void;
|
|
21
|
+
upgrade<TData = unknown>(request: Request, options?: {
|
|
22
|
+
data?: TData;
|
|
23
|
+
headers?: HeadersInit;
|
|
24
|
+
}): boolean;
|
|
25
|
+
url?: URL;
|
|
26
|
+
}
|
|
27
|
+
export interface BunWebSocketHandler<TData = unknown> {
|
|
28
|
+
backpressureLimit?: number;
|
|
29
|
+
close?(socket: BunServerWebSocket<TData>, code: number, reason: string): void | Promise<void>;
|
|
30
|
+
closeOnBackpressureLimit?: boolean;
|
|
31
|
+
data?: TData;
|
|
32
|
+
drain?(socket: BunServerWebSocket<TData>): void | Promise<void>;
|
|
33
|
+
error?(socket: BunServerWebSocket<TData>, error: Error): void | Promise<void>;
|
|
34
|
+
idleTimeout?: number;
|
|
35
|
+
maxPayloadLength?: number;
|
|
36
|
+
message?(socket: BunServerWebSocket<TData>, message: BunWebSocketMessage): void | Promise<void>;
|
|
37
|
+
open?(socket: BunServerWebSocket<TData>): void | Promise<void>;
|
|
38
|
+
perMessageDeflate?: boolean | {
|
|
39
|
+
compress?: boolean | '128KB' | '16KB' | '256KB' | '32KB' | '3KB' | '4KB' | '64KB' | '8KB' | 'dedicated' | 'disable' | 'shared';
|
|
40
|
+
decompress?: boolean | '128KB' | '16KB' | '256KB' | '32KB' | '3KB' | '4KB' | '64KB' | '8KB' | 'dedicated' | 'disable' | 'shared';
|
|
41
|
+
};
|
|
42
|
+
publishToSelf?: boolean;
|
|
43
|
+
sendPings?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface BunWebSocketBinding<TData = unknown> {
|
|
46
|
+
fetch(request: Request, server: BunServerLike): Response | Promise<Response> | undefined | Promise<Response | undefined>;
|
|
47
|
+
websocket: BunWebSocketHandler<TData>;
|
|
48
|
+
}
|
|
49
|
+
export interface BunWebSocketBindingHost {
|
|
50
|
+
configureWebSocketBinding<TData>(binding: BunWebSocketBinding<TData> | undefined): void;
|
|
51
|
+
}
|
|
52
|
+
export type TypedOnMessageHandler<TEvents extends Record<string, unknown>, K extends keyof TEvents> = (payload: TEvents[K], socket: BunServerWebSocket, request: Request) => void | Promise<void>;
|
|
53
|
+
export interface WebSocketGatewayContext {
|
|
54
|
+
request: Request;
|
|
55
|
+
socket: BunServerWebSocket;
|
|
56
|
+
}
|
|
57
|
+
export type WebSocketModuleOptions = SharedWebSocketModuleOptions;
|
|
58
|
+
//# sourceMappingURL=bun-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun-types.d.ts","sourceRoot":"","sources":["../../src/bun/bun-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,IAAI,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAE1F,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO;IACjD,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,IAAI,CAAC;IAClE,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACrC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC3D,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACnG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,sBAAsB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7C,OAAO,CAAC,KAAK,GAAG,OAAO,EACrB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE;QACR,IAAI,CAAC,EAAE,KAAK,CAAC;QACb,OAAO,CAAC,EAAE,WAAW,CAAC;KACvB,GACA,OAAO,CAAC;IACX,GAAG,CAAC,EAAE,GAAG,CAAC;CACX;AAED,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO;IAClD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChE,KAAK,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,IAAI,CAAC,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,iBAAiB,CAAC,EACd,OAAO,GACP;QACE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;QAC/H,UAAU,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;KAClI,CAAC;IACN,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO;IAClD,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACzH,SAAS,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CACzF;AAED,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,kBAAkB,EAC1B,OAAO,EAAE,OAAO,KACb,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAAG,4BAA4B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../../src/bun/bun.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
|
package/dist/bun/bun.js
ADDED
package/dist/bun.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bun.d.ts","sourceRoot":"","sources":["../src/bun.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
package/dist/bun.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './bun/bun.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ModuleType } from '@fluojs/runtime';
|
|
2
|
+
import type { WebSocketModuleOptions } from './cloudflare-workers-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Explicit Cloudflare Workers websocket module entrypoint.
|
|
5
|
+
*/
|
|
6
|
+
export declare class CloudflareWorkersWebSocketModule {
|
|
7
|
+
/**
|
|
8
|
+
* Registers the Cloudflare Workers websocket lifecycle service for request-upgrade gateway hosting.
|
|
9
|
+
*
|
|
10
|
+
* @param options Websocket gateway runtime options for guards, limits, heartbeat, and shutdown behavior.
|
|
11
|
+
* @returns A runtime module definition scoped to the Cloudflare Workers websocket adapter.
|
|
12
|
+
*/
|
|
13
|
+
static forRoot(options?: WebSocketModuleOptions): ModuleType;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=cloudflare-workers-module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare-workers-module.d.ts","sourceRoot":"","sources":["../../src/cloudflare-workers/cloudflare-workers-module.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAY5E;;GAEG;AACH,qBAAa,gCAAgC;IAC3C;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,sBAA2B,GAAG,UAAU;CAOjE"}
|