fixed tests
This commit is contained in:
129
public/js/services/WebSocketClient.ts
Normal file
129
public/js/services/WebSocketClient.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { assertUnreachable, ReadOnlySubject, Subject } from '@techniker-me/tools';
|
||||
import type { ISignalingMessage, IWebRTCClient } from '../interfaces/IWebRTCClient.ts';
|
||||
|
||||
export enum WebSocketClientStatus {
|
||||
Offline = 0,
|
||||
Connecting = 1,
|
||||
Online = 2,
|
||||
Reconnecting = 3,
|
||||
Error = 4,
|
||||
Closed = 5,
|
||||
}
|
||||
|
||||
export type WebSocketClientStatusType = 'offline' | 'connecting' | 'online' | 'reconnecting' | 'error' | 'closed';
|
||||
|
||||
export class WebSocketClientStatusMapping {
|
||||
public static convertWebSocketClientStatusToWebSocketClientStatusType(status: WebSocketClientStatus): WebSocketClientStatusType {
|
||||
switch (status) {
|
||||
case WebSocketClientStatus.Offline:
|
||||
return 'offline';
|
||||
case WebSocketClientStatus.Connecting:
|
||||
return 'connecting';
|
||||
case WebSocketClientStatus.Online:
|
||||
return 'online';
|
||||
case WebSocketClientStatus.Reconnecting:
|
||||
return 'reconnecting';
|
||||
case WebSocketClientStatus.Error:
|
||||
return 'error';
|
||||
case WebSocketClientStatus.Closed:
|
||||
return 'closed';
|
||||
default:
|
||||
assertUnreachable(status);
|
||||
}
|
||||
}
|
||||
|
||||
public static convertWebSocketClientStatusTypeToWebSocketClientStatus(status: WebSocketClientStatusType): WebSocketClientStatus {
|
||||
switch (status) {
|
||||
case 'offline':
|
||||
return WebSocketClientStatus.Offline;
|
||||
case 'connecting':
|
||||
return WebSocketClientStatus.Connecting;
|
||||
case 'online':
|
||||
return WebSocketClientStatus.Online;
|
||||
case 'reconnecting':
|
||||
return WebSocketClientStatus.Reconnecting;
|
||||
case 'error':
|
||||
return WebSocketClientStatus.Error;
|
||||
case 'closed':
|
||||
return WebSocketClientStatus.Closed;
|
||||
default:
|
||||
assertUnreachable(status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class WebSocketClient implements IWebRTCClient {
|
||||
private readonly _status: Subject<WebSocketClientStatus> = new Subject<WebSocketClientStatus>(WebSocketClientStatus.Offline);
|
||||
private readonly _readOnlyStatus: ReadOnlySubject<WebSocketClientStatus> = new ReadOnlySubject<WebSocketClientStatus>(this._status);
|
||||
private ws: WebSocket | null = null;
|
||||
private role: 'publisher' | 'subscriber';
|
||||
private messageHandlers: Map<string, (message: ISignalingMessage) => void> = new Map();
|
||||
|
||||
constructor(role: 'publisher' | 'subscriber') {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
get status(): ReadOnlySubject<WebSocketClientStatus> {
|
||||
return this._readOnlyStatus;
|
||||
}
|
||||
|
||||
async connect(): Promise<void> {
|
||||
this._status.value = WebSocketClientStatus.Online;
|
||||
return new Promise((resolve, reject) => {
|
||||
const wsUrl = `ws://localhost:3000/ws?role=${this.role}`;
|
||||
this.ws = new WebSocket(wsUrl);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
this._status.value = WebSocketClientStatus.Online;
|
||||
resolve();
|
||||
};
|
||||
|
||||
this.ws.onerror = (error) => {
|
||||
this._status.value = WebSocketClientStatus.Error;
|
||||
reject(error);
|
||||
};
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
const message: ISignalingMessage = JSON.parse(event.data);
|
||||
this.handleMessage(message);
|
||||
} catch (error) {
|
||||
console.error('Failed to parse WebSocket message:', error);
|
||||
}
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this._status.value = WebSocketClientStatus.Closed;
|
||||
this.ws = null;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
this.ws = null;
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(message: ISignalingMessage): void {
|
||||
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
||||
this.ws.send(JSON.stringify(message));
|
||||
}
|
||||
}
|
||||
|
||||
isConnected(): boolean {
|
||||
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
||||
}
|
||||
|
||||
onMessage(type: string, handler: (message: ISignalingMessage) => void): void {
|
||||
this.messageHandlers.set(type, handler);
|
||||
}
|
||||
|
||||
private handleMessage(message: ISignalingMessage): void {
|
||||
const handler = this.messageHandlers.get(message.type);
|
||||
if (handler) {
|
||||
handler(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user