UNPKG

create-fetch-hooks

Version:

A simple and powerful custom React hook (useApi) that simplifies API requests with automatic loading and error states. Ideal for clean and maintainable data fetching in React components.

59 lines (58 loc) 3.77 kB
import { refreshToken } from "./refreshToken"; import { FetchError } from "./types/FetchError"; import { mergeHeaders } from "./utils/mergeHeader"; import { removeMultipleSlashes } from "./utils/removeMultipleSlashes"; export async function get(baseApiUrl, url, options) { var _a, _b, _c, _d, _e, _f; let responseCode; const cleanedUrl = removeMultipleSlashes(`${baseApiUrl}/${url}`); const maxRetries = (_a = options === null || options === void 0 ? void 0 : options.retryCount) !== null && _a !== void 0 ? _a : ((options === null || options === void 0 ? void 0 : options.callRefreshToken) ? 1 : 0); // Default to 0 retries if not specified const retryDelay = (_b = options === null || options === void 0 ? void 0 : options.retryDelay) !== null && _b !== void 0 ? _b : 0; // Default to 1 second delay for (let attempt = 0; attempt <= maxRetries; attempt++) { try { const response = await fetch(cleanedUrl, { method: "GET", headers: mergeHeaders(options === null || options === void 0 ? void 0 : options.headers, { Authorization: `Bearer ${localStorage.getItem((options === null || options === void 0 ? void 0 : options.accessTokenLocalStorageKey) || "")}`, test2: Math.floor(Math.random() * 9000).toString(), }), signal: options === null || options === void 0 ? void 0 : options.signal, }); responseCode = response.status; if (!response.ok) { const error = new FetchError(`HTTP error! Status: ${response.status}`, response, response.status); // If 403 and retries remain, wait and retry const refreshTokenConfig = (_c = options === null || options === void 0 ? void 0 : options.callRefreshToken) === null || _c === void 0 ? void 0 : _c.call(options); if ((refreshTokenConfig === null || refreshTokenConfig === void 0 ? void 0 : refreshTokenConfig.on.includes(response.status)) && attempt < maxRetries) { // await new Promise((resolve) => { await new Promise((resolve) => setTimeout(resolve, retryDelay)); await refreshToken(baseApiUrl, refreshTokenConfig.endpoint, refreshTokenConfig.body, refreshTokenConfig.saveAccessTokenFromResponse); continue; // Retry the request } throw error; } const res = await response.json(); (_d = options === null || options === void 0 ? void 0 : options.onSuccess) === null || _d === void 0 ? void 0 : _d.call(options, res); return; // Exit on success } catch (err) { if (err instanceof Error && err.name !== "AbortError") { const fetchErr = err instanceof FetchError ? err : new FetchError(err.message); if (attempt === maxRetries) { // Only call onError on the final attempt (_e = options === null || options === void 0 ? void 0 : options.onError) === null || _e === void 0 ? void 0 : _e.call(options, fetchErr); if (fetchErr.status !== undefined) { responseCode = fetchErr.status || undefined; } } } } finally { if (attempt === maxRetries) { // Call onResponseGot only on the final attempt (_f = options === null || options === void 0 ? void 0 : options.onResponseGot) === null || _f === void 0 ? void 0 : _f.call(options, cleanedUrl, removeMultipleSlashes(cleanedUrl.replace(baseApiUrl, "/")).split("?")[0], responseCode); } } } }