/** * Generic api method that can be adapted to any fetch request */ const makeFetch = (method, url, body, options) => { let opts = { method: method, headers: { 'Content-Type': 'application/json;charset=utf-8' }, body: (body !== null) ? JSON.stringify(body) : null }; if (typeof options !== 'undefined') { opts = Object.assign(opts, options); } return fetch(url, opts) .then(response => { if (response.ok) { return response.json(); } if (response.status === 422) { console.log('422 error') return response.json().then(response => { throw ValidationException(response) }); } if (response.status === 403) { console.log('403 error') throw AccessException(response); } throw { name: 'Exception', sta: response.status, txt: response.statusText, err: new Error(), violations: response.body }; }); } /** * Fetch results with certain parameters */ const _fetchAction = (page, uri, params) => { const item_per_page = 50; if (params === undefined) { params = {}; } let url = uri + '?' + new URLSearchParams({ item_per_page, page, ...params }); return fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json;charset=utf-8' }, }).then(response => { if (response.ok) { return response.json(); } throw Error({ m: response.statusText }); }); }; const fetchResults = async (uri, params) => { let promises = [], page = 1; let firstData = await _fetchAction(page, uri, params); promises.push(Promise.resolve(firstData.results)); if (firstData.pagination.more) { do { page = ++page; promises.push(_fetchAction(page, uri, params).then(r => Promise.resolve(r.results))); } while (page * firstData.pagination.items_per_page < firstData.count) } return Promise.all(promises).then(values => values.flat()); }; const fetchScopes = () => { return fetchResults('/api/1.0/main/scope.json'); }; /** * Error objects to be thrown */ const ValidationException = (response) => { const error = {}; error.name = 'ValidationException'; error.violations = response.violations.map((violation) => `${violation.title}: ${violation.propertyPath}`); error.titles = response.violations.map((violation) => violation.title); error.propertyPaths = response.violations.map((violation) => violation.propertyPath); return error; } const AccessException = (response) => { const error = {}; error.name = 'AccessException'; error.violations = ['You are not allowed to perform this action']; return error; } export { makeFetch, fetchResults, fetchScopes }