import { Observable } from 'rxjs' import { map } from 'rxjs/operators' import { webSocket, WebSocketSubject, WebSocketSubjectConfig } from 'rxjs/webSocket' import { Update } from '../types' import { Source } from './source' export class WebsocketSource implements Source { private websocket$: WebSocketSubject>> | undefined constructor ( private readonly url: string, ) { } watch$ (): Observable> { const fullConfig: WebSocketSubjectConfig>> = { url: this.url, openObserver: { next: () => { this.websocket$!.next(document.cookie as any) }, }, } this.websocket$ = webSocket(fullConfig) return this.websocket$.pipe( map(res => { if (isRpcSuccess(res)) return res.result if (isRpcError(res)) throw new RpcError(res.error) }), ) as Observable> } } interface RPCBase { jsonrpc: '2.0' } export interface RPCSuccess extends RPCBase { result: T } export interface RPCError extends RPCBase { error: { code: number // 34 means unauthenticated message: string data: { details: string } } } export type RPCResponse = RPCSuccess | RPCError function isRpcError (arg: { error: Error } | { result: Result}): arg is { error: Error } { return !!(arg as any).error } function isRpcSuccess (arg: { error: Error } | { result: Result}): arg is { result: Result } { return !!(arg as any).result } class RpcError { code: number message: string details: string constructor (e: RPCError['error']) { this.code = e.code this.message = e.message this.details = e.data.details } }