import { invoke, transformCallback } from '@tauri-apps/api/tauri' export interface MessageKind { type: T data: D } export interface CloseFrame { code: number reason: string } export type Message = MessageKind<'Text', string> | MessageKind<'Binary', number[]> | MessageKind<'Ping', number[]> | MessageKind<'Pong', number[]> | MessageKind<'Close', CloseFrame | null> export default class WebSocket { id: number private listeners: Array<(arg: Message) => void> constructor(id: number, listeners: Array<(arg: Message) => void>) { this.id = id this.listeners = listeners } static async connect(url: string, options?: any): Promise { const listeners: Array<(arg: Message) => void> = [] const handler = (message: Message) => { listeners.forEach(l => l(message)) } return invoke('plugin:websocket|connect', { url, callbackFunction: transformCallback(handler), options }).then(id => new WebSocket(id, listeners)) } addListener(cb: (arg: Message) => void) { this.listeners.push(cb) } send(message: Message | string | number[]): Promise { let m: Message if (typeof message === 'string') { m = { type: 'Text', data: message } } else if (typeof message === 'object' && ('type' in message)) { m = message } else if (Array.isArray(message)) { m = { type: 'Binary', data: message } } else { throw new Error('invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array') } return invoke('plugin:websocket|send', { id: this.id, message: m }) } disconnect(): Promise { return this.send({ type: 'Close', data: { code: 1000, reason: 'Disconnected by client' } }) } }