UNPKG

ra-core

Version:

Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React

110 lines (97 loc) 3.72 kB
import HttpError from './HttpError'; import { stringify } from 'query-string'; export interface Options extends RequestInit { user?: { authenticated?: boolean; token?: string; }; } export const createHeadersFromOptions = (options: Options): Headers => { const requestHeaders = (options.headers || new Headers({ Accept: 'application/json', })) as Headers; const hasBody = options && options.body; const isContentTypeSet = requestHeaders.has('Content-Type'); const isGetMethod = !options?.method || options?.method === 'GET'; const isFormData = options?.body instanceof FormData; const shouldSetContentType = hasBody && !isContentTypeSet && !isGetMethod && !isFormData; if (shouldSetContentType) { requestHeaders.set('Content-Type', 'application/json'); } if (options.user && options.user.authenticated && options.user.token) { requestHeaders.set('Authorization', options.user.token); } return requestHeaders; }; /** * Utility function to make HTTP calls. It's similar to the HTML5 `fetch()`, except it handles JSON decoding and HTTP error codes automatically. * * @param url the URL to call * @param options the options to pass to the HTTP call * @param options.user the user object, used for the Authorization header * @param options.user.token the token to pass as the Authorization header * @param options.user.authenticated whether the user is authenticated or not (the Authorization header will be set only if this is true) * @param options.headers the headers to pass to the HTTP call * * @returns {Promise} the Promise for a response object containing the following properties: * - status: the HTTP status code * - headers: the HTTP headers * - body: the response body * - json: the response body parsed as JSON */ export const fetchJson = (url, options: Options = {}) => { const requestHeaders = createHeadersFromOptions(options); return fetch(url, { ...options, headers: requestHeaders }) .then(response => response.text().then(text => ({ status: response.status, statusText: response.statusText, headers: response.headers, body: text, })) ) .then(({ status, statusText, headers, body }) => { let json; try { json = JSON.parse(body); } catch (e) { // not json, no big deal } if (status < 200 || status >= 300) { return Promise.reject( new HttpError( (json && json.message) || statusText, status, json ) ); } return Promise.resolve({ status, headers, body, json }); }); }; export const queryParameters = stringify; const isValidObject = value => { if (!value) { return false; } const isArray = Array.isArray(value); const isBuffer = typeof Buffer !== 'undefined' && Buffer.isBuffer(value); const isObject = Object.prototype.toString.call(value) === '[object Object]'; const hasKeys = !!Object.keys(value).length; return !isArray && !isBuffer && isObject && hasKeys; }; export const flattenObject = (value: any, path: string[] = []) => { if (isValidObject(value)) { return Object.assign( {}, ...Object.keys(value).map(key => flattenObject(value[key], path.concat([key])) ) ); } else { return path.length ? { [path.join('.')]: value } : value; } };