Skip to content

Instantly share code, notes, and snippets.

@anymaniax
Last active January 9, 2024 19:04
Show Gist options
  • Save anymaniax/1efd5ccd7829ab73dc239935739e35da to your computer and use it in GitHub Desktop.
Save anymaniax/1efd5ccd7829ab73dc239935739e35da to your computer and use it in GitHub Desktop.
type HttpInterceptor = (
options: FetchOptions,
) => Promise<FetchOptions> | FetchOptions;
type HttpInstance = {
baseURL: string;
headers: Record<string, string>;
};
export const HTTP_INSTANCE: HttpInstance = {
baseURL: '',
headers: {},
};
export type FetchOptions = {
baseURL?: string;
headers?: Record<string, string>;
url: string;
method:
| 'get'
| 'post'
| 'put'
| 'delete'
| 'patch'
| 'GET'
| 'POST'
| 'PUT'
| 'DELETE'
| 'PATCH';
params?: any;
data?: any;
responseType?: string;
signal?: AbortSignal;
};
export type FetchResponse<T = unknown> = {
data: T;
headers: {
authorization?: string | null;
};
};
export type FetchError<T = unknown> = {
data: T;
status: number;
};
export const getResponseBody = <T>(response: Response): Promise<T> => {
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
return response.json();
}
if (contentType && contentType.includes('application/pdf')) {
return response.blob() as Promise<T>;
}
return response.text() as Promise<T>;
};
export const fetchInstance = async <T>(
config: FetchOptions,
init?: ResponseInit
): Promise<FetchResponse<T>> => {
const isFormData = config.headers?.['Content-Type'] === 'multipart/form-data';
const isJson = config.headers?.['Content-Type'] === 'application/json';
const baseUrl = config.baseURL;
const headers = {
...config.headers,
...(isJson ? { 'Content-Type': 'application/json' } : {}),
};
// Remove Content-Type header if it's not needed to avoid issues
if (!isJson) {
delete headers['Content-Type'];
}
const response = await fetch(
`${baseUrl}${config.url}` +
(config.params ? `?${new URLSearchParams(config.params)}` : ''),
{
method: config.method,
...(config.data
? { body: !isFormData ? JSON.stringify(config.data) : config.data }
: {}),
headers,
signal: config.signal,
},
);
const data = await getResponseBody<T>(response);
if (!response.ok) {
throw {
status: response.status,
data,
};
}
return {
headers: {
authorization: response.headers.get('authorization'),
},
data,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment