ice/packages/plugin-request/src/request.ts

125 lines
4.1 KiB
TypeScript

import type { AxiosRequestConfig, CancelTokenStatic, CancelStatic } from 'axios';
import axios from 'axios';
// https://github.com/axios/axios#request-config
const DEFAULT_CONFIG = {};
const axiosInstances = {
default: axios.create(DEFAULT_CONFIG),
};
/**
* Create an axios instance.
* @param instanceName
*/
export function createAxiosInstance(instanceName?: string) {
if (instanceName) {
if (axiosInstances[instanceName]) {
return axiosInstances;
}
axiosInstances[instanceName] = axios.create(DEFAULT_CONFIG);
}
return axiosInstances;
}
export function setAxiosInstance(requestConfig, axiosInstance) {
const { interceptors = {}, ...requestOptions } = requestConfig;
Object.keys(requestOptions).forEach(key => {
axiosInstance.defaults[key] = requestOptions[key];
});
function isExist(handlers, [fulfilled, rejected]) {
return handlers.some(item => item.fulfilled === fulfilled && item.rejected === rejected);
}
// Add request interceptor.
if (interceptors.request) {
const [fulfilled, rejected] = [
interceptors.request.onConfig || function (config) { return config; },
interceptors.request.onError || function (error) { return Promise.reject(error); },
];
if (isExist(axiosInstance.interceptors.request.handlers, [fulfilled, rejected])) return;
axiosInstance.interceptors.request.use(fulfilled, rejected);
}
// Add response interceptor.
if (interceptors.response) {
const [fulfilled, rejected] = [
interceptors.response.onConfig || function (response) { return response; },
interceptors.response.onError || function (error) { return Promise.reject(error); },
];
if (isExist(axiosInstance.interceptors.response.handlers, [fulfilled, rejected])) return;
axiosInstance.interceptors.response.use(fulfilled, rejected);
}
}
interface RequestConfig<D> extends AxiosRequestConfig<D> {
instanceName?: string;
withFullResponse?: boolean;
}
export interface RequestProps {
get: <T = any, D = any>(url: string, config?: RequestConfig<D>) => Promise<T>;
delete: <T = any, D = any>(url: string, config?: RequestConfig<D>) => Promise<T>;
head: <T = any, D = any>(url: string, config?: RequestConfig<D>) => Promise<T>;
options: <T = any, D = any>(url: string, config?: RequestConfig<D>) => Promise<T>;
post: <T = any, D = any>(url: string, data?: D, config?: RequestConfig<D>) => Promise<T>;
put: <T = any, D = any>(url: string, data?: D, config?: RequestConfig<D>) => Promise<T>;
patch: <T = any, D = any>(url: string, data?: D, config?: RequestConfig<D>) => Promise<T>;
}
interface Request extends RequestProps {
<T = any, D = any>(options: RequestConfig<D>): Promise<T>;
<T = any, D = any>(url: string, config?: RequestConfig<D>): Promise<T>;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel: (value: any) => boolean;
}
/**
* Request, return response.data | response
* @param options Reference: https://github.com/axios/axios#request-config
*/
const request = async function <T = any, D = any>(options: RequestConfig<D>): Promise<T> {
try {
const instanceName = options.instanceName ? options.instanceName : 'default';
const axiosInstance = createAxiosInstance()[instanceName];
if (!(typeof axiosInstance === 'function')) {
throw new Error(`unknown ${instanceName} in request method`);
}
const response = await axiosInstance(options);
if (axiosInstance.defaults.withFullResponse || options.withFullResponse) {
return response;
}
return response.data;
} catch (error) {
console.error(error);
throw error;
}
} as Request;
// Provide aliases for supported request methods
['delete', 'get', 'head', 'options'].forEach((method) => {
request[method] = function <T = any, D = any>(url, config) {
return request<T, D>(Object.assign(config || {}, {
method,
url,
}));
};
});
['post', 'put', 'patch'].forEach((method) => {
request[method] = function <T = any, D = any>(url, data, config) {
return request<T, D>(Object.assign(config || {}, {
method,
url,
data,
}));
};
});
request.CancelToken = axios.CancelToken;
request.isCancel = axios.isCancel;
export { request };