import axios, { AxiosRequestConfig, AxiosError, Method, AxiosResponse } from "axios"; export class ApiRequestError extends Error { public code: number | undefined; public response: unknown | undefined; constructor(message: string, res?: unknown, code?: number) { super(message); this.name = "ApiRequestError"; this.code = code; this.response = res; } } type HttpMethod = Extract; const httpMethods = { get: axios.get, post: axios.post, put: axios.put, delete: axios.delete, patch: axios.patch }; export function fetcher(url: string): Promise; export function fetcher( url: string, init?: Omit & { method?: Exclude } ): Promise; export function fetcher( url: string, init: Omit & { method: "DELETE" } ): Promise; export async function fetcher( url: string, init?: Omit & { method?: HttpMethod } ): Promise> { const { method = "get", data, ...config } = init || {}; const fullConfig: AxiosRequestConfig = { method, ...config, timeout: 10000 }; try { const m = method.toLowerCase() as keyof typeof httpMethods; if (["post", "patch", "put"].includes(m)) { const response = await httpMethods[m](url, data, fullConfig); return response.data; } else if (m === "delete") { const response = await axios.delete(url, fullConfig); return response; } else { const response = await httpMethods[m](url, fullConfig); return response.data; } } catch (error) { const axiosError = error as AxiosError; if (axiosError.response) { const { status, data } = axiosError.response; throw new ApiRequestError(`HTTP error! status: ${status}`, data, status); } else if (axiosError.request) { throw new ApiRequestError("No response received", undefined, -1); } else { throw new ApiRequestError(axiosError.message || "Unknown error"); } } }