@mojojs/core
Version:
Real-time web framework
77 lines • 2.38 kB
JavaScript
import EventEmitter, { on } from 'node:events';
/**
* WebSocket connection class.
*/
class WebSocket extends EventEmitter {
constructor(ws, handshake, options) {
super({ captureRejections: true });
this.handshake = handshake;
this.jsonMode = options.jsonMode ?? false;
this._ws = ws;
ws.on('error', error => this.emit('error', error));
ws.on('message', this._safeMessageHandler.bind(this));
const safeHandler = this._safeHandler;
ws.on('close', safeHandler.bind(this, 'close'));
ws.on('ping', safeHandler.bind(this, 'ping'));
ws.on('pong', safeHandler.bind(this, 'pong'));
}
async *[Symbol.asyncIterator]() {
try {
for await (const [message] of this._messageIterator()) {
yield message;
}
}
catch (error) {
if (!(error instanceof Error) || error.name !== 'AbortError')
throw error;
}
}
/**
* Close WebSocket connection.
*/
close(code, reason) {
this._ws.close(code, reason);
}
/**
* Send WebSocket ping frame.
*/
async ping(data) {
return await new Promise(resolve => this._ws.ping(data, undefined, () => resolve()));
}
/**
* Send WebSocket message.
*/
async send(message) {
if (this.jsonMode === false)
return await new Promise(resolve => this._ws.send(message, () => resolve()));
return new Promise(resolve => this._ws.send(JSON.stringify(message), () => resolve()));
}
_messageIterator() {
const ac = new AbortController();
this._ws.on('close', () => ac.abort());
return on(this, 'message', { signal: ac.signal });
}
_safeHandler(event, ...args) {
try {
this.emit(event, ...args);
}
catch (error) {
this.emit('error', error);
}
}
_safeMessageHandler(message, isBinary) {
try {
if (this.jsonMode === false) {
this.emit('message', isBinary ? message : message.toString());
}
else {
this.emit('message', JSON.parse(message.toString()));
}
}
catch (error) {
this.emit('error', error);
}
}
}
export { WebSocket };
//# sourceMappingURL=websocket.js.map