|
@@ -0,0 +1,274 @@
|
|
|
+import Axios from 'axios'
|
|
|
+import { ResCode } from './constant'
|
|
|
+
|
|
|
+import type { AxiosResponse, AxiosRequestConfig } from 'axios'
|
|
|
+
|
|
|
+export type ResErrorHandler = <D, T extends ResData<D>>(
|
|
|
+ response: AxiosResponse<T>,
|
|
|
+ data?: T
|
|
|
+) => void
|
|
|
+export type ReqErrorHandler = <T>(
|
|
|
+ err: Error,
|
|
|
+ response: AxiosRequestConfig<T>
|
|
|
+) => void
|
|
|
+export type ResData<T> = {
|
|
|
+ code: ResCode
|
|
|
+ message: string
|
|
|
+ data: T
|
|
|
+ msg: string
|
|
|
+}
|
|
|
+export type Hook = {
|
|
|
+ before?: (config: AxiosRequestConfig) => void
|
|
|
+ after?: (config: AxiosRequestConfig) => void
|
|
|
+}
|
|
|
+
|
|
|
+export const axiosFactory = () => {
|
|
|
+ const axiosRaw = Axios.create()
|
|
|
+ const axiosConfig = {
|
|
|
+ token: localStorage.getItem('token'),
|
|
|
+ unTokenSet: [] as string[],
|
|
|
+ unReqErrorSet: [] as string[],
|
|
|
+ unResErrorSet: [] as string[],
|
|
|
+ resErrorHandler: [] as ResErrorHandler[],
|
|
|
+ reqErrorHandler: [] as ReqErrorHandler[],
|
|
|
+ unLoadingSet: [] as string[],
|
|
|
+ hook: [] as Hook[]
|
|
|
+ }
|
|
|
+
|
|
|
+ type AxiosConfig = typeof axiosConfig
|
|
|
+ type ExponseApi<K extends keyof AxiosConfig> = {
|
|
|
+ set: (val: AxiosConfig[K]) => void
|
|
|
+ } & (AxiosConfig[K] extends Array<any>
|
|
|
+ ? {
|
|
|
+ add: (...val: AxiosConfig[K]) => void
|
|
|
+ del: (...val: AxiosConfig[K]) => void
|
|
|
+ }
|
|
|
+ : { del: () => void })
|
|
|
+
|
|
|
+ const getExponseApi = <K extends keyof AxiosConfig>(
|
|
|
+ key: K
|
|
|
+ ): ExponseApi<K> => {
|
|
|
+ let axiosObj = axiosConfig[key] as any[]
|
|
|
+ const apis: any = {
|
|
|
+ set(val: AxiosConfig[K]) {
|
|
|
+ axiosObj = axiosConfig[key] = val as any
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Array.isArray(axiosObj)) {
|
|
|
+ apis.add = (...val: any[]) => {
|
|
|
+ axiosObj.push(...val)
|
|
|
+ }
|
|
|
+ apis.del = (...val: any[]) => {
|
|
|
+ if (val) {
|
|
|
+ apis.set(axiosObj.filter((item: any) => !val?.includes(item)) as any)
|
|
|
+ } else {
|
|
|
+ axiosObj.length = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ apis.del = () => {
|
|
|
+ axiosConfig[key] = undefined as any
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return apis
|
|
|
+ }
|
|
|
+
|
|
|
+ const getToken = () => axiosConfig.token
|
|
|
+ const setToken = (token: string) => {
|
|
|
+ localStorage.setItem('token', token)
|
|
|
+ axiosConfig.token = token
|
|
|
+ }
|
|
|
+ const delToken = () => {
|
|
|
+ localStorage.removeItem('token')
|
|
|
+ axiosConfig.token = null
|
|
|
+ }
|
|
|
+
|
|
|
+ const {
|
|
|
+ set: setUnsetTokenURLS,
|
|
|
+ add: addUnsetTokenURLS,
|
|
|
+ del: delUnsetTokenURLS
|
|
|
+ } = getExponseApi('unTokenSet')
|
|
|
+
|
|
|
+ const {
|
|
|
+ set: setResErrorHandler,
|
|
|
+ add: addResErrorHandler,
|
|
|
+ del: delResErrorHandler
|
|
|
+ } = getExponseApi('resErrorHandler')
|
|
|
+
|
|
|
+ const {
|
|
|
+ set: setUnsetReqErrorURLS,
|
|
|
+ add: addUnsetReqErrorURLS,
|
|
|
+ del: delUnsetReqErrorURLS
|
|
|
+ } = getExponseApi('unReqErrorSet')
|
|
|
+
|
|
|
+ const {
|
|
|
+ set: setReqErrorHandler,
|
|
|
+ add: addReqErrorHandler,
|
|
|
+ del: delReqErrorHandler
|
|
|
+ } = getExponseApi('reqErrorHandler')
|
|
|
+
|
|
|
+ const {
|
|
|
+ set: setUnsetResErrorURLS,
|
|
|
+ add: addUnsetResErrorURLS,
|
|
|
+ del: delUnsetResErrorURLS
|
|
|
+ } = getExponseApi('unResErrorSet')
|
|
|
+
|
|
|
+ const { set: setHook, add: addHook, del: delHook } = getExponseApi('hook')
|
|
|
+
|
|
|
+ const setDefaultURI = (url: string) => {
|
|
|
+ axiosRaw.defaults.baseURL = url
|
|
|
+ }
|
|
|
+
|
|
|
+ const matchURL = (urls: string[], config: AxiosRequestConfig<any>) =>
|
|
|
+ config && config.url && urls.includes(config.url)
|
|
|
+
|
|
|
+ const callErrorHandler = (key: 'req' | 'res', ...args: any[]) => {
|
|
|
+ Promise.resolve().then(() => {
|
|
|
+ const api = `${key}ErrorHandler`
|
|
|
+ ;(axiosConfig as any)[api].forEach((handler: any) => handler(...args))
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ axiosRaw.interceptors.request.use(config => {
|
|
|
+ for (const hook of axiosConfig.hook) {
|
|
|
+ hook.before && hook.before(config)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!matchURL(axiosConfig.unTokenSet, config)) {
|
|
|
+ if (!axiosConfig.token) {
|
|
|
+ if (!matchURL(axiosConfig.unReqErrorSet, config)) {
|
|
|
+ const error = new Error('缺少token')
|
|
|
+ callErrorHandler('req', error, config)
|
|
|
+ throw error
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ config.headers = {
|
|
|
+ ...config.headers,
|
|
|
+ token: axiosConfig.token
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return config
|
|
|
+ })
|
|
|
+
|
|
|
+ axiosRaw.interceptors.response.use(
|
|
|
+ (response: AxiosResponse<ResData<any>>) => {
|
|
|
+ for (const hook of axiosConfig.hook) {
|
|
|
+ hook.after && hook.after(response.config)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (matchURL(axiosConfig.unResErrorSet, response.config)) {
|
|
|
+ return response
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.status !== 200) {
|
|
|
+ callErrorHandler('res', response)
|
|
|
+ throw new Error(response.statusText)
|
|
|
+ } else if (response.data.code !== ResCode.SUCCESS) {
|
|
|
+ callErrorHandler('res', response, response.data)
|
|
|
+ if (response.data.code === ResCode.TOKEN_INVALID) {
|
|
|
+ delToken()
|
|
|
+ }
|
|
|
+ throw new Error(response?.data?.message)
|
|
|
+ } else {
|
|
|
+ return response.data.data
|
|
|
+ }
|
|
|
+ },
|
|
|
+ err => {
|
|
|
+ for (const hook of axiosConfig.hook) {
|
|
|
+ hook.after && hook.after(err.config)
|
|
|
+ }
|
|
|
+ if (!matchURL(axiosConfig.unResErrorSet, err.config)) {
|
|
|
+ callErrorHandler('res', err.response)
|
|
|
+ }
|
|
|
+ throw new Error(err.response ? err.response.statusText : err)
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ type AxiosProcess = {
|
|
|
+ getUri(config?: AxiosRequestConfig): string
|
|
|
+ request<R = any, D = any>(config: AxiosRequestConfig<D>): Promise<R>
|
|
|
+ get<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ delete<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ head<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ options<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ post<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ put<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ patch<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ postForm<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ putForm<R = any, D = unknown>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ patchForm<R = any, D = any>(
|
|
|
+ url: string,
|
|
|
+ data?: D,
|
|
|
+ config?: AxiosRequestConfig<D>
|
|
|
+ ): Promise<R>
|
|
|
+ }
|
|
|
+
|
|
|
+ interface AxiosInstanceProcess extends AxiosProcess {
|
|
|
+ <R = any>(config: AxiosRequestConfig): Promise<R>
|
|
|
+ <R = any>(url: string, config?: AxiosRequestConfig): Promise<R>
|
|
|
+ }
|
|
|
+
|
|
|
+ const axios: AxiosInstanceProcess = axiosRaw as any
|
|
|
+
|
|
|
+ return {
|
|
|
+ axios,
|
|
|
+ getToken,
|
|
|
+ setToken,
|
|
|
+ delToken,
|
|
|
+ setUnsetTokenURLS,
|
|
|
+ addUnsetTokenURLS,
|
|
|
+ delUnsetTokenURLS,
|
|
|
+ setResErrorHandler,
|
|
|
+ addResErrorHandler,
|
|
|
+ delResErrorHandler,
|
|
|
+ setUnsetReqErrorURLS,
|
|
|
+ addUnsetReqErrorURLS,
|
|
|
+ delUnsetReqErrorURLS,
|
|
|
+ setReqErrorHandler,
|
|
|
+ addReqErrorHandler,
|
|
|
+ delReqErrorHandler,
|
|
|
+ setUnsetResErrorURLS,
|
|
|
+ addUnsetResErrorURLS,
|
|
|
+ delUnsetResErrorURLS,
|
|
|
+ setDefaultURI,
|
|
|
+ setHook,
|
|
|
+ addHook,
|
|
|
+ delHook
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export default axiosFactory
|