import { Observable, Subject } from "rxjs"; import { Socket as ClientSocket } from "socket.io-client"; import { Socket as SocketForConnectedClient } from "socket.io" import { handleClientSocketConnection, handleNewSocketClient, startClientSocketConnection, startSocketServer, writeFile } from "../utils/socket.utils"; import { ITransportReceiving, ITransportTransmitting, ReceiverProfile, TransmitterProfile, TransportEventNotification, TransportMessage, TransportSettings } from "../interface/ITransport.interface"; /* Just code in the context that this websocket service will be handling multiple UI clients. Can think about the server communication at a later time. */ export class WebsocketTransportService implements ITransportTransmitting, ITransportReceiving { private socketReceiverProfile: ReceiverProfile[] = [] private incomingMessage: Subject = new Subject() // this is only for client roles only atm private eventNotification: Subject = new Subject() constructor(setting: TransportSettings) { if (setting.profileInfo.port) { startSocketServer(setting.profileInfo.port as number).subscribe({ next: (connectedClient: SocketForConnectedClient) => { handleNewSocketClient(connectedClient, this.eventNotification, this.socketReceiverProfile) }, error: error => console.error(error), }) } // this is for those who wants to act as receiver. Usually for web browser, but servers can use this too. if (setting.profileInfo.url) { startClientSocketConnection(setting.profileInfo.url).then((socket: ClientSocket) => { handleClientSocketConnection(socket, this.incomingMessage).subscribe(this.eventNotification) }).catch((error) => { console.error(`WebsocketTransport ERROR:`, error) }) } } // for transmission(Server Only, not applicable for client Socket) public async transmit(message: TransportMessage): Promise { return new Promise((resolve, reject) => { let receiverInstance = this.socketReceiverProfile.find(obj => obj.uuid === message.receiverID); if (receiverInstance) { (receiverInstance?.instance as SocketForConnectedClient).emit(message.event, message.payload) resolve('Message called for delivery...') } else { reject(`Receiver cannot be found or doesn't exist...`) } }) } public getTransportEventNotification(): Observable { return this.eventNotification as Observable } // for client UI eg public receive(): Observable { return this.incomingMessage.asObservable() } }