capacitor-cors-bypass-enhanced
Version:
Enhanced Capacitor plugin for CORS bypass with HTTP/2, HTTP/3, gRPC, GraphQL, file operations, and advanced networking features. Modular TypeScript definitions for better maintainability.
115 lines (100 loc) • 3.45 kB
text/typescript
import type {
WebSocketConnectionOptions,
WebSocketConnection,
WebSocketMessageEvent,
WebSocketConnectionChangeEvent,
} from '../definitions';
/**
* WebSocket Manager
* Handles WebSocket connections with CORS bypass
*/
export class WebSocketManager {
private wsConnections = new Map<string, WebSocket>();
private connectionCounter = 0;
private notifyListeners: (eventName: string, data: any) => void;
constructor(notifyListeners: (eventName: string, data: any) => void) {
this.notifyListeners = notifyListeners;
}
/**
* Create a WebSocket connection
*/
async createWebSocketConnection(options: WebSocketConnectionOptions): Promise<WebSocketConnection> {
const connectionId = `ws_${++this.connectionCounter}`;
const { url, protocols, headers, timeout = 10000 } = options;
return new Promise((resolve, reject) => {
const ws = new WebSocket(url, protocols);
this.wsConnections.set(connectionId, ws);
const timeoutId = setTimeout(() => {
ws.close();
this.wsConnections.delete(connectionId);
reject(new Error('WebSocket connection timeout'));
}, timeout);
ws.onopen = () => {
clearTimeout(timeoutId);
this.notifyListeners('webSocketConnectionChange', {
connectionId,
status: 'connected',
} as WebSocketConnectionChangeEvent);
resolve({
connectionId,
status: 'connected',
});
};
ws.onmessage = (event) => {
this.notifyListeners('webSocketMessage', {
connectionId,
data: event.data,
type: typeof event.data === 'string' ? 'text' : 'binary',
} as WebSocketMessageEvent);
};
ws.onerror = () => {
clearTimeout(timeoutId);
this.notifyListeners('webSocketConnectionChange', {
connectionId,
status: 'error',
error: 'WebSocket connection error',
} as WebSocketConnectionChangeEvent);
};
ws.onclose = () => {
this.wsConnections.delete(connectionId);
this.notifyListeners('webSocketConnectionChange', {
connectionId,
status: 'disconnected',
} as WebSocketConnectionChangeEvent);
};
this.notifyListeners('webSocketConnectionChange', {
connectionId,
status: 'connecting',
} as WebSocketConnectionChangeEvent);
});
}
/**
* Close a WebSocket connection
*/
async closeWebSocketConnection(options: { connectionId: string }): Promise<void> {
const { connectionId } = options;
const connection = this.wsConnections.get(connectionId);
if (connection) {
connection.close();
this.wsConnections.delete(connectionId);
}
}
/**
* Send data through WebSocket
*/
async sendWebSocketMessage(options: { connectionId: string; message: string }): Promise<void> {
const { connectionId, message } = options;
const connection = this.wsConnections.get(connectionId);
if (connection && connection.readyState === WebSocket.OPEN) {
connection.send(message);
} else {
throw new Error('WebSocket connection not found or not open');
}
}
/**
* Get all active WebSocket connections
*/
getWebSocketConnections(): Map<string, WebSocket> {
return this.wsConnections;
}
}