UNPKG

@abalmus/request

Version:

Core utils, fetch wrapper, querystring utils

196 lines (153 loc) 4.83 kB
import { encode } from '../utils/index'; import { METHODS, DEFAULT_OPTIONS } from './constants'; import 'isomorphic-fetch'; import 'whatwg-fetch'; interface FetchOptionsI { CSRFToken?: string; headers?: object; method?: string; port?: number; url: string; } function isObject(obj) { return (typeof obj === 'object') && (obj !== null); } class FetchClient { post?(url?: string): FetchClient; get?(url?: string): FetchClient; put?(url?: string): FetchClient; delete?(url?: string): FetchClient; private __request: any = {}; private __queryStringParams: any = ''; constructor(private options?: FetchOptionsI) { this.__request = Object.assign({}, DEFAULT_OPTIONS, options); METHODS.map(this.__createMethod.bind(this)); } /* test-code */ __testApi() { return this.__request }; /* end-test-code */ public send(data: string | object): Promise<any> { checkSubmissionData(data); const { __request } = this; const body = ( typeof data === 'string' ? data : encode(data) ); return this.__doFetch( this.__appendQueryString(__request.url), Object.assign({}, __request, {body}) ); } public sendJson(data: string| object): Promise<any> { return this.send(( typeof data === 'string' ? JSON.stringify(JSON.parse(data)) : JSON.stringify(data) )); } public sendForm(form: HTMLFormElement) { const formData = new FormData(form); const { __request } = this; return this.__doFetch( form.action, Object.assign({}, __request, {body: formData}) ) } public query(query: string | object) { checkSubmissionData(query); if (isObject(query)) { query = encode(query); } this.__queryStringParams = query; return this; } public headers(field: string | object, value?: string) { if (isObject(field)) { for (let key in field as Object) { if (Object.prototype.hasOwnProperty.call(field, key)) { this.headers(key, field[key]) } } return this; } let existingHeaderName = this.hasHeader(field); this.__request.headers[existingHeaderName || field] = value; return this; } public hasHeader(name) { let headers; let lowercaseHeaders; name = name.toLowerCase(); headers = Object.keys(this.__request.headers); lowercaseHeaders = headers.map(header => { return header.toLowerCase() }); for (let i = 0; i < lowercaseHeaders.length; i++) { if (lowercaseHeaders[i] === name) { return headers[i] } } return false } private __appendQueryString(url: string) { if (url.split('?').length > 1) { return `${url}&${this.__queryStringParams}`; } return ( this.__queryStringParams ? `${url}?${this.__queryStringParams}` : url ); } private __doFetch(url: string, options: RequestInit) { return fetch(url, options) .then(validateHttpResponse) .catch(error => error); } private __applyMethodSpecificHeaders(method) { switch(method) { case 'POST': !this.hasHeader('Content-Type') && this.headers({ 'Content-Type': 'application/x-www-form-urlencoded' }); break; } } private __createMethod(method) { this[method.toLowerCase()] = (url: string, port?: number) => { if (!url && !this.__request.url) throw new Error(`Required parameter "url" in ${method.toLowerCase()} call is missed.`); if (url) this.__request.url = url; this.__request.method = method; this.__applyMethodSpecificHeaders(method); return this; }; } } function validateHttpResponse(response) { const { status, ok } = response; if (status >= 400 || !ok) { throw new Error(JSON.stringify({ status, message: 'Bad response from server' })); } return response; } function checkSubmissionData(data) { if (!data || (!isObject(data) && typeof data !== 'string')) { throw new Error('Data format is not correct please use object or string') } } const json = (resp) => resp.json(); const text = (resp) => resp.text(); export const response = { json, text } export const request = (options?: FetchOptionsI) => new FetchClient(options);