bfcache: server - WebSocketServer

This commit is contained in:
2025-09-17 23:50:13 -04:00
parent 351ccf3e2a
commit ce1d4561a2
4 changed files with 122 additions and 2 deletions

View File

@@ -8,7 +8,8 @@
"format": "prettier --write .",
"lint": "eslint --max-warnings 0 .",
"prelint:fix": "bun run format",
"lint:fix": "eslint --fix ."
"lint:fix": "eslint --fix .",
"start:dev": "bun run --watch src"
},
"devDependencies": {
"@eslint/css": "0.11.0",
@@ -26,5 +27,28 @@
"dependencies": {
"@techniker-me/logger": "0.0.15",
"@techniker-me/tools": "2025.0.16"
},
"author": {
"name": "Alexander Zinn",
"email": "zinntechniker@gmail.com",
"git+url": "https://github.com/zinntechniker"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/zinntechniker/websocket-relay-server"
},
"homepage": "https://github.com/zinntechniker/websocket-relay-server",
"bugs": {
"url": "https://github.com/zinntechniker/websocket-relay-server/issues"
},
"keywords": [
"websocket",
"relay",
"server"
],
"engines": {
"node": ">=20.0.0",
"bun": ">=1.2.21"
}
}

View File

@@ -0,0 +1,93 @@
import type {ServerWebSocket, WebSocketCompressor} from 'bun';
import type {Seconds, Bytes} from './types/Units';
export type PerMessageDeflate =
| boolean
| {
compress?: boolean | WebSocketCompressor;
decomporess?: boolean | WebSocketCompressor;
};
export type WebSocketServerOptions = {
maxPayloadLength?: Bytes;
idleTimeout?: Seconds;
backPressureLimit?: Bytes;
closeOnBackPressureLimit?: boolean;
sendPings?: boolean;
publishToSelf?: boolean;
perMessageDeflate?: PerMessageDeflate;
onSocketError?: (client: ServerWebSocket, error: Error) => void;
onSocketOpen?: (client: ServerWebSocket) => void;
onSocketMessage?: (client: ServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
onSocketDrain?: (client: ServerWebSocket) => void;
onSocketClose?: (client: ServerWebSocket) => void;
};
const webSocketServerDefaults: WebSocketServerOptions = {
maxPayloadLength: 16777216,
idleTimeout: 120,
backPressureLimit: 1048576,
closeOnBackPressureLimit: false,
sendPings: true,
publishToSelf: true,
perMessageDeflate: true
};
export default class WebSocketServer {
private readonly _maxPayloadLength: Bytes;
private readonly _idleTimeout: Seconds;
private readonly _backPressureLimit: Bytes;
private readonly _closeOnBackPressureLimit: boolean;
private readonly _sendPings: boolean;
private readonly _publishToSelf: boolean;
private readonly _perMessageDeflate: PerMessageDeflate;
public readonly error?: (client: ServerWebSocket, error: Error) => void;
public readonly open?: (client: ServerWebSocket) => void;
public readonly message?: (client: ServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
public readonly drain?: (client: ServerWebSocket) => void;
public readonly close?: (client: ServerWebSocket) => void;
constructor(options?: WebSocketServerOptions) {
this._maxPayloadLength = options?.maxPayloadLength ?? webSocketServerDefaults.maxPayloadLength!;
this._idleTimeout = options?.idleTimeout ?? webSocketServerDefaults.idleTimeout!;
this._backPressureLimit = options?.backPressureLimit ?? webSocketServerDefaults.backPressureLimit!;
this._closeOnBackPressureLimit = options?.closeOnBackPressureLimit ?? webSocketServerDefaults.closeOnBackPressureLimit!;
this._sendPings = options?.sendPings ?? webSocketServerDefaults.sendPings!;
this._publishToSelf = options?.publishToSelf ?? webSocketServerDefaults.publishToSelf!;
this._perMessageDeflate = options?.perMessageDeflate ?? webSocketServerDefaults.perMessageDeflate!;
this.error = options?.onSocketError;
this.open = options?.onSocketOpen;
this.message = options?.onSocketMessage;
this.drain = options?.onSocketDrain;
this.close = options?.onSocketClose;
}
get maxPayloadLength(): Bytes {
return this._maxPayloadLength;
}
get idleTimeout(): Seconds {
return this._idleTimeout;
}
get backPressureLimit(): Bytes {
return this._backPressureLimit;
}
get closeOnBackPressureLimit(): boolean {
return this._closeOnBackPressureLimit;
}
get sendPings(): boolean {
return this._sendPings;
}
get publishToSelf(): boolean {
return this._publishToSelf;
}
get perMessageDeflate(): PerMessageDeflate {
return this._perMessageDeflate;
}
}

View File

@@ -0,0 +1,3 @@
export type Bytes = number;
export type Seconds = number;

View File

@@ -9,7 +9,7 @@
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"verbatimModuleSyntax": false,
"noEmit": true,
"strict": true,