UNPKG

rest-api-handler

Version:
263 lines (223 loc) 6.29 kB
import resolveProcessors from './resolveProcessors.js'; import * as dataFormats from './data-formats.js'; import { JSON as JSON$1, FORM_DATA, URL_ENCODED } from './data-formats.js'; /** * Class for handling responses and requests. */ class Api { /** * Base api url */ /** * Base http headers */ /** * Base settings for Fetch Request */ /** * List of processors that parse response from server. */ /** * List of formatter you can use to process content of body request. */ /** * Constructor. * * @param apiUrl - Base api url * @param processors - List of processors that parse response from server. * @param defaultHeaders - Base settings for Fetch Request * @param defaultOptions - List of processors that parse response from server. */ constructor(apiUrl, processors = [], defaultHeaders = {}, defaultOptions = {}) { this.apiUrl = apiUrl; this.defaultHeaders = defaultHeaders; this.defaultOptions = defaultOptions; this.processors = processors; } /** * Convert data in object to format of Fetch body. * * @param data - Data to convert * @param to - Format to which convert the data. Default is JSON. * @returns Converted data * * @example * const body = Api.convertData({ a: 'b' }, Api.FORMATS.JSON); * // output is {"a":"b"} */ static convertData(data, to = JSON$1) { if (to === FORM_DATA) { const formData = new FormData(); Object.entries(data).forEach(([key, value]) => { formData.append(key, value); }); return formData; } if (to === URL_ENCODED) { return Api.convertParametersToUrl(data).slice(1); } return JSON.stringify(data); } /** * Convert object to url parameters string. * * @param parameters - List of parameters * @returns Encoded string with ? prefix and variables separated by & * * @example * const parameters = Api.convertData({ a: '%b%' }); * // output is ?a=%25b%25 */ static convertParametersToUrl(parameters) { const keys = Object.keys(parameters); if (keys.length === 0) { return ''; } return `?${keys.map(key => { return `${key}=${encodeURIComponent(parameters[key])}`; }).join('&')}`; } /** * Set default headers. * * @param headers - HTTP headers */ setDefaultHeaders(headers) { this.defaultHeaders = headers; } /** * Add default HTTP header. * * @param name - Name of header * @param value - Value for header * @example * api.setDefaultHeader('content-type', 'application/json'); */ setDefaultHeader(name, value) { this.defaultHeaders[name] = value; } /** * Remove default header. * * @param name - Name of header */ removeDefaultHeader(name) { delete this.defaultHeaders[name]; } /** * Get default headers. * * @returns Get Default headers */ getDefaultHeaders() { return this.defaultHeaders; } /** * Fetch API url. * * @protected * @param request - Fetch request * @returns Fetch response */ fetchRequest(request) { return fetch(request); } /** * Request given API endpoint. * * @param namespace - Api endpoint or full url * @param method - Request method eg. POST or GET * @param options - Fetch options * @param headers - Custom headers * @returns processed response * @example * const { data } = await api.request('ad', 'POST', { * body: '{"ad":1}' * }) * * const { data } = await api.request('http://i-can-request-full-url.com/?a=b', 'GET') */ async request(namespace, method, options = {}, headers = {}) { const urlToRequest = namespace.indexOf('http') === 0 ? namespace : `${this.apiUrl}/${namespace}`; // eslint-disable-next-line compat/compat const request = new Request(urlToRequest, { ...this.defaultOptions, method, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line compat/compat headers: new Headers({ ...this.getDefaultHeaders(), ...headers }), ...options }); const response = await this.fetchRequest(request); return resolveProcessors(response, this.processors, request); } /** * Send a request with body. * * @protected * @param namespace - api endpoint * @param method - api method * @param data - body JSON parameters * @param format - format of body request * @param headers - custom headers * @returns processed response */ requestWithBody(namespace, method, data, format, headers = {}) { return this.request(namespace, method, { body: Api.convertData(data, format) }, headers); } /** * Send a GET request. * * @param namespace - api endpoint * @param parameters - get parameters * @param headers - custom headers * @returns processed response * * @example * const { data } = await api.get('brand', { id: 5 }) * // will call YOUR_URI/brand?id=5 * console.log(data); */ get(namespace, parameters = {}, headers = {}) { return this.request(`${namespace}${Api.convertParametersToUrl(parameters)}`, 'GET', {}, headers); } /** * Send a POST request. * * @param namespace - Api endpoint * @param data - Request object * @param format - Format of body request * @param headers - custom headers * @returns Processed response */ post(namespace, data = {}, format = JSON$1, headers = {}) { return this.requestWithBody(namespace, 'POST', data, format, headers); } /** * Send a PUT request. * * @param namespace - Api endpoint * @param data - Request object * @param format - Format of body request * @param headers - custom headers * @returns Processed response */ put(namespace, data = {}, format = JSON$1, headers = {}) { return this.requestWithBody(namespace, 'PUT', data, format, headers); } /** * Send a DELETE request. * * @param namespace - Api endpoint * @param headers - custom headers * @returns Processed response */ delete(namespace, headers = {}) { return this.request(namespace, 'DELETE', {}, headers); } } Api.FORMATS = dataFormats; export { Api as default };