121 lines
3.3 KiB
TypeScript
121 lines
3.3 KiB
TypeScript
import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios'
|
|
import Config from '@/config/config.export'
|
|
import { useSpinnerStore } from '@/store/spinnerStore'
|
|
|
|
export function useAxios() {
|
|
const requestHandler = (config: InternalAxiosRequestConfig) => {
|
|
useSpinnerStore.getState().setIsShow(true)
|
|
return config
|
|
}
|
|
|
|
const responseHandler = (response: AxiosResponse) => {
|
|
/* spinner 조작 커스텀이 필요한 경우 api 응답 헤더에 spinner-state: true 추가 */
|
|
if (!response.headers['spinner-state']) {
|
|
useSpinnerStore.getState().setIsShow(false)
|
|
}
|
|
response.data = transferResponse(response)
|
|
return response
|
|
}
|
|
|
|
const errorHandler = (error: any) => {
|
|
useSpinnerStore.getState().setIsShow(false)
|
|
return Promise.reject(error)
|
|
}
|
|
|
|
const createAxiosInstance = (url: string | null | undefined) => {
|
|
const baseURL = url || Config().baseUrl
|
|
return axios.create({
|
|
baseURL,
|
|
headers: {
|
|
Accept: 'application/json',
|
|
},
|
|
})
|
|
}
|
|
|
|
const axiosInstance = (url: string | null | undefined) => {
|
|
const instance = axios.create({
|
|
baseURL: url || Config().baseUrl,
|
|
headers: {
|
|
Accept: 'application/json',
|
|
},
|
|
})
|
|
|
|
instance.interceptors.request.use(
|
|
// (config) => {
|
|
// return config
|
|
// },
|
|
// (error) => {
|
|
// return Promise.reject(error)
|
|
// },
|
|
(config) => requestHandler(config),
|
|
(error) => errorHandler(error),
|
|
)
|
|
|
|
instance.interceptors.response.use(
|
|
// (response) => {
|
|
// response.data = transferResponse(response)
|
|
// return response
|
|
// },
|
|
// (error) => {
|
|
// return Promise.reject(error)
|
|
// },
|
|
(response) => responseHandler(response),
|
|
(error) => errorHandler(error),
|
|
)
|
|
|
|
return instance
|
|
}
|
|
|
|
// response데이터가 array, object에 따라 분기하여 키 변환
|
|
const transferResponse = (response: any) => {
|
|
if (!response.data) return response.data
|
|
|
|
// 배열인 경우 각 객체의 키를 변환
|
|
if (Array.isArray(response.data)) {
|
|
return response.data.map((item: any) => transformObjectKeys(item))
|
|
}
|
|
|
|
// 단일 객체인 경우
|
|
return transformObjectKeys(response.data)
|
|
}
|
|
|
|
// camel case object 반환
|
|
const transformObjectKeys = (obj: any): any => {
|
|
if (Array.isArray(obj)) {
|
|
return obj.map(transformObjectKeys)
|
|
}
|
|
|
|
if (obj !== null && typeof obj === 'object') {
|
|
return Object.keys(obj).reduce((acc: any, key: string) => {
|
|
let transformedKey = key
|
|
|
|
// Handle uppercase snake_case (e.g., USER_NAME -> userName)
|
|
// Handle lowercase snake_case (e.g., user_name -> userName)
|
|
if (/^[A-Z_]+$/.test(key) || /^[a-z_]+$/.test(key)) {
|
|
transformedKey = snakeToCamel(key)
|
|
}
|
|
// Handle single uppercase word (e.g., ROLE -> role)
|
|
else if (/^[A-Z]+$/.test(key)) {
|
|
transformedKey = key.toLowerCase()
|
|
}
|
|
// Preserve existing camelCase
|
|
|
|
acc[transformedKey] = transformObjectKeys(obj[key])
|
|
return acc
|
|
}, {})
|
|
}
|
|
|
|
return obj
|
|
}
|
|
|
|
const snakeToCamel = (str: string): string => {
|
|
return str.toLowerCase().replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace('-', '').replace('_', ''))
|
|
}
|
|
|
|
return {
|
|
axiosInstance,
|
|
transferResponse,
|
|
transformObjectKeys,
|
|
}
|
|
}
|