UNPKG

@softvisio/core

Version:
155 lines (117 loc) 3.9 kB
import fetch from "#lib/fetch"; import result from "#lib/result"; import Events from "./events.js"; export default class extends Events { #_url; #dispatcher; // public publish ( name, args ) { this.#call( "/publish", [ name, ...args ], true ); } async call ( method, args ) { return this.#call( method, args ); } voidCall ( method, args ) { this.#call( method, args, true ); } // private get #url () { if ( !this.#_url ) { const url = new URL( this.protocol + "//" + this.hostname ); url.port = this.port; url.pathname = this.pathname; if ( url.protocol === "ws:" ) { url.protocol = "http:"; } else if ( url.protocol === "wss:" ) { url.protocol = "https:"; } if ( this.locale ) { url.searchParams.set( "locale", this.locale ); } this.#_url = url; } return this.#_url; } async #call ( method, args, isVoidCall ) { var url = new URL( this.#url ), signal, fetchOptions; if ( typeof method === "object" ) { let voidCall; ( { method, args, signal, "void": voidCall, ...fetchOptions } = method ); isVoidCall ||= voidCall; } // aborted if ( signal?.aborted ) return result( -32_817 ); // add method url.pathname += this.prepateMethodName( method ); const headers = { "content-type": "application/json", }; if ( isVoidCall ) headers[ "x-api-void-call" ] = "true"; if ( this.token ) headers.Authorization = "Bearer " + this.token; var res; try { this.#dispatcher ??= new fetch.Dispatcher( { "checkCertificate": this.checkCertificate, } ); res = await fetch( url, { ...fetchOptions, "method": args.length ? "POST" : "GET", "mode": "cors", headers, "body": args.length ? JSON.stringify( args ) : null, signal, "dispatcher": this.#dispatcher, } ); if ( isVoidCall ) return; // aborted if ( !res.ok && signal?.aborted ) return result( -32_817 ); const contentType = res.headers.get( "content-type" ) ?? ""; let msg; // json if ( contentType.startsWith( "application/json" ) ) { try { msg = await res.json(); } catch { // message decode error throw result( -32_807 ); } } else { // request error if ( !res.ok ) { throw res; } // invalid content type else { throw result( -32_803 ); } } res = result.fromJsonRpc( msg ); } catch ( e ) { res = result.catch( e ); } // session is disabled if ( res.status === -32_813 ) this.emit( "sessionDisable" ); // session was deleted if ( res.status === -32_815 ) this.emit( "sessionDelete" ); // access denied if ( res.status === -32_811 ) this.emit( "accessDenied" ); // authorization if ( !isVoidCall && res.status === -32_812 ) { if ( this.onAuthorization && ( await this.onAuthorization() ) ) { // repeat request return this.#call( method, args ); } } return res; } }