diff --git a/packages/fetch/src/main.ts b/packages/fetch/src/main.ts index 14a13e4f..c1834714 100644 --- a/packages/fetch/src/main.ts +++ b/packages/fetch/src/main.ts @@ -1,10 +1,62 @@ import {handleCacheStrategy_, logger_, processOptions_, cacheSupported} from './core'; -import type {FetchOptions} from './type'; +import type {FetchOptions, ResponseError, ResponseSuccess} from './type'; +import type {Json, JsonObject} from '@alwatr/type-helper'; export {cacheSupported}; export type * from './type'; +/** + * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy, + * remove duplicates, etc. + * + * @see {@link FetchOptions} + * @see {@link ResponseSuccess} + * @see {@link ResponseError} + * + * @param options Fetch options. + * + * @returns A success or error response. + * + * @example + * ```typescript + * const responseJson = await fetchJson({ + * url: '/api/products', + * queryParameters: {limit: 10}, + * timeout: 8_000, + * retry: 3, + * cacheStrategy: 'stale_while_revalidate', + * cacheDuplicate: 'auto', + * }); + * ``` + */ +export async function fetchJson(options: FetchOptions): Promise | ResponseError> { + let response; + let responseText; + let responseJson; + try { + response = await fetch(options); + responseText = await response.text(); + responseJson = JSON.parse(responseText) as ResponseSuccess; + responseJson.ok = true; + responseJson.statusCode = response.status; + return responseJson; + } + catch (error) { + const responseError: ResponseError = { + ok: false, + statusCode: response?.status, + statusText: response?.statusText, + errorCode: (responseJson?.errorCode as string) ?? (error as Error).message, + responseText, + meta: responseJson?.meta as JsonObject, + }; + + logger_.accident('fetchJson', 'fetch_failed', {responseError, error}); + return responseError; + } +} + /** * It's a wrapper around the browser's `fetch` function that adds retry pattern, timeout, cacheStrategy, * remove duplicates, etc. diff --git a/packages/fetch/src/type.ts b/packages/fetch/src/type.ts index 699823a7..166b7ae4 100644 --- a/packages/fetch/src/type.ts +++ b/packages/fetch/src/type.ts @@ -1,4 +1,4 @@ -import type {Dictionary, Json} from '@alwatr/type-helper'; +import type {Dictionary, Json, JsonObject} from '@alwatr/type-helper'; /** * Represents the available HTTP methods. @@ -132,7 +132,21 @@ export interface FetchOptions extends RequestInit { * Alwatr token scheme */ alwatrAuth?: { - userId: string, - userToken: string, - } + userId: string; + userToken: string; + }; +} + +export type ResponseSuccess = T & { + ok: true; + statusCode: number; +}; + +export type ResponseError = { + ok: false; + statusCode?: number; + statusText?: string; + errorCode: string; + responseText?: string; + meta?: JsonObject; }