All files / src/api provider.ts

25% Statements 5/20
13.33% Branches 2/15
50% Functions 1/2
26.31% Lines 5/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71                                                                    5x 5x 5x 5x                 5x                                                
type Fetch = (input: any, init?: any) => Promise<any>
 
/** Response to an API call.  */
export interface APIResponse {
    json?: any
    text: string
    status: number
    headers: Record<string, string>
}
 
export interface APIProvider {
    /**
     * Call an API endpoint and return the response.
     * Provider is responsible for JSON encoding the params and decoding the response.
     * @argument path The endpoint path, e.g. `/v1/chain/get_info`
     * @argument params The request body if any.
     */
    call(path: string, params?: unknown): Promise<APIResponse>
}
 
export interface FetchProviderOptions {
    /**
     * Fetch instance, must be provided in non-browser environments.
     * You can use the node-fetch package in Node.js.
     */
    fetch?: Fetch
}
 
/** Default provider that uses the Fetch API to call a single node. */
export class FetchProvider implements APIProvider {
    readonly url: string
    readonly fetch: Fetch
 
    constructor(url: string, options: FetchProviderOptions = {}) {
        url = url.trim()
        Iif (url.endsWith('/')) url = url.slice(0, -1)
        this.url = url
        Iif (!options.fetch) {
            if (typeof window !== 'undefined' && window.fetch) {
                this.fetch = window.fetch.bind(window)
            } else if (typeof global !== 'undefined' && global.fetch) {
                this.fetch = global.fetch.bind(global)
            } else {
                throw new Error('Missing fetch')
            }
        } else {
            this.fetch = options.fetch
        }
    }
 
    async call(path: string, params?: unknown) {
        const url = this.url + path
        const response = await this.fetch(url, {
            method: 'POST',
            body: params !== undefined ? JSON.stringify(params) : undefined,
        })
        const text = await response.text()
        let json: any
        try {
            json = JSON.parse(text)
        } catch {
            // ignore json parse errors
        }
        const headers = {}
        for (const [key, value] of response.headers.entries()) {
            headers[key] = value
        }
        return {headers, status: response.status, json, text}
    }
}