import { emitter } from '@amatiasq/emitter'; import { SocketTransport } from '../transport.js'; /** * One connection on the server, speaking typed JSON. The mirror image of * `JsonSocket`: `TIn` is what the client sends, `TOut` is what you send back. * * This was `NiceSocket`, and it used to `extend` the `ws` `WebSocket` class — * which meant `NiceSocketServer` could not simply construct one (the instances * come from `ws`, already built) and grafted the two methods onto each incoming * socket with `Object.create(ws, {…descriptors})`. Taking the transport as a * constructor argument instead removes both the inheritance and the hack. */ export class JsonConnection { private readonly emitMessage = emitter(); readonly onMessage = this.emitMessage.subscribe; private readonly emitClose = emitter(); readonly onClose = this.emitClose.subscribe; constructor(private readonly transport: SocketTransport) { transport.onMessage(data => this.processMessage(data)); transport.onClose(() => this.emitClose()); } send(value: TOut) { this.transport.send(JSON.stringify(value)); } close() { this.transport.close(); } private processMessage(data: string) { let message: TIn; try { message = JSON.parse(data) as TIn; } catch (error) { console.warn('Invalid JSON:', data); return; } this.emitMessage(message); } }