From e9ceb0f12bf34a5e8b9384a5d7fef70e3262df4b Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:13:24 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20api=20wrapping=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe --- client/src/apis/fetcher.ts | 126 +++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 client/src/apis/fetcher.ts diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts new file mode 100644 index 000000000..55c28d708 --- /dev/null +++ b/client/src/apis/fetcher.ts @@ -0,0 +1,126 @@ +type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; + +type Body = ReadableStream | XMLHttpRequestBodyInit; +type HeadersType = [string, string][] | Record | Headers; + +export type ObjectQueryParams = Record; + +type RequestProps = { + baseUrl: string; + endpoint: string; + headers?: HeadersType; + body?: Body | object | null; + queryParams?: ObjectQueryParams; + // errorMessage: string; +}; + +type FetcherProps = RequestProps & { + method: Method; +}; + +type Options = { + method: Method; + headers: HeadersType; + body?: Body | null; +}; + +const objectToQueryString = (params: ObjectQueryParams): string => { + return Object.entries(params) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +}; + +export const requestGet = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({ + ...args, + method: 'GET', + headers, + }); + + const data: T = await response.json(); + return data; +}; + +export const requestPatch = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PATCH', headers, ...args}); +}; + +export const requestPut = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PUT', headers, ...args}); +}; + +export const requestPost = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'POST', headers, ...args}); +}; + +export const requestDelete = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'DELETE', headers, ...args}); +}; + +const fetcher = ({method, baseUrl, endpoint, headers, body, queryParams}: FetcherProps) => { + // const token = generateBasicToken(USER_ID, USER_PASSWORD); + const options = { + method, + headers: { + 'Content-Type': 'application/json', + // Authorization: token, + ...headers, + }, + body: body ? JSON.stringify(body) : null, + }; + + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + return errorHandler(url, options); +}; + +// class ErrorWithHeader extends Error { +// header: string; + +// constructor(header: string, message: string) { +// super(message); +// this.name = this.constructor.name; +// this.header = header; +// } +// } + +const errorHandler = async (url: string, options: Options) => { + try { + const response = await fetch(url, options); + if (!response.ok) { + const serverErrorMessage = await response.text(); + throw new Error(serverErrorMessage || ''); // 받은 에러 메세지가 없는 경우는 서버에게.. + } + return response; + } catch (error) { + console.error(error); + throw new Error('아 에러났다;; 인생이 행복해질거에요 에러덕분에요ㅎㅎ'); + // throw new ErrorWithHeader(errorMessageHeader, getErrorMessage(error)); + } +}; + +// export const ERROR_MESSAGE = { +// SYSTEM_FAULT: 'system error. 관리자에게 문의하십시오', +// OFFLINE: '네트워크 연결이 끊어졌습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.', +// UNKNOWN: '알 수 없는 에러입니다. 관리자에게 문의해주세요. (연락처...)', +// }; + +// const getErrorMessage = (error: unknown) => { +// return ERROR_MESSAGE.UNKNOWN; + +// if (error instanceof TypeError) return ERROR_MESSAGE.OFFLINE; + +// if (error instanceof Error) { +// const mappedErrorMessage = Object.entries(SERVER_ERROR_MESSAGE).find(([key]) => { +// const upperCaseErrorMessage = convertToUpperCase(error.message.split(SERVER_ERROR_MESSAGE_DIVIDER)[0]); + +// return upperCaseErrorMessage.includes(key); +// })?.[1]; + +// return mappedErrorMessage ?? ERROR_MESSAGE.UNKNOWN; +// } + +// return ERROR_MESSAGE.UNKNOWN; +// };