diff --git a/src/api/EpiData.ts b/src/api/EpiData.ts index 142d2c5..8612320 100644 --- a/src/api/EpiData.ts +++ b/src/api/EpiData.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/restrict-template-expressions */ import UIkit from 'uikit'; import { appendIssueToTitle } from '../components/dialogs/utils'; import { @@ -43,11 +44,23 @@ const ENDPOINT = process.env.EPIDATA_ENDPOINT_URL; export const fetchOptions: RequestInit = process.env.NODE_ENV === 'development' ? { cache: 'force-cache' } : {}; +function processResponse(response: Response): Promise { + if (response.ok) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return response.json(); + } + return response.text().then((text) => { + throw new Error(`[${response.status}] ${text}`); + }); +} + export function fetchImpl(url: URL): Promise { const urlGetS = url.toString(); if (urlGetS.length < 4096) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return fetch(url.toString(), fetchOptions).then((d) => d.json()); + return fetch(url.toString(), fetchOptions).then((d) => { + return processResponse(d); + }); } const params = new URLSearchParams(url.searchParams); url.searchParams.forEach((d) => url.searchParams.delete(d)); @@ -56,7 +69,9 @@ export function fetchImpl(url: URL): Promise { ...fetchOptions, method: 'POST', body: params, - }).then((d) => d.json()); + }).then((d) => { + return processResponse(d); + }); } // generic epidata loader @@ -147,18 +162,42 @@ export function loadDataSet( url.searchParams.set('format', 'json'); return fetchImpl[]>(url) .then((res) => { - const data = loadEpidata(title, res, columns, columnRenamings, { _endpoint: endpoint, ...params }); - if (data.datasets.length == 0) { + try { + const data = loadEpidata(title, res, columns, columnRenamings, { _endpoint: endpoint, ...params }); + if (data.datasets.length == 0) { + return UIkit.modal + .alert( + ` +
+ API Link returned no data, which suggests that the API has no available information for the selected location. +
`, + ) + .then(() => null); + } + return data; + } catch (error) { + console.warn('failed loading data', error); + // EpiData API error - JSON with "message" property + if ('message' in res) { + return UIkit.modal + .alert( + ` +
+ [f01] Failed to fetch API data from API Link:
${res['message']} +
`, + ) + .then(() => null); + } + // Fallback for generic error return UIkit.modal .alert( `
- API Link returned no data. + [f02] Failed to fetch API data from API Link:
${error}
`, ) .then(() => null); } - return data; }) .catch((error) => { console.warn('failed fetching data', error); @@ -166,7 +205,7 @@ export function loadDataSet( .alert( `
- Failed to fetch API data from API Link. + [f03] Failed to fetch API data from API Link:
${error}
`, ) .then(() => null);