axios-miniprogram/src/core/Axios.ts

552 lines
10 KiB
TypeScript
Raw Normal View History

import { isString } from '../helpers/isTypes';
import { dispatchRequest } from '../request/dispatchRequest';
2023-04-21 18:09:32 +08:00
import { CancelToken } from '../request/cancel';
import { AxiosTransformer } from '../request/transformData';
import { deepMerge } from '../helpers/deepMerge';
2023-03-23 20:09:00 +08:00
import {
AxiosAdapter,
2023-03-28 20:35:40 +08:00
AxiosAdapterRequestMethod,
AxiosAdapterPlatformTask,
2023-03-28 20:35:40 +08:00
AxiosAdapterRequestConfig,
2023-04-09 21:01:43 +08:00
AxiosAdapterResponseData,
2023-04-22 16:12:32 +08:00
} from '../adpater/createAdapter';
import InterceptorManager, {
Interceptor,
InterceptorExecutor,
} from './InterceptorManager';
2023-04-09 21:01:43 +08:00
import { mergeConfig } from './mergeConfig';
import {
PLAIN_METHODS,
WITH_DATA_METHODS,
WITH_PARAMS_METHODS,
} from '../constants/methods';
2023-04-25 14:28:28 +08:00
import MiddlewareManager, {
MiddlewareContext,
2023-04-25 14:28:28 +08:00
MiddlewareNext,
MiddlewareUse,
} from './MiddlewareManager';
2023-03-23 20:09:00 +08:00
/**
*
*/
2023-03-28 20:35:40 +08:00
export type AxiosRequestMethod =
| AxiosAdapterRequestMethod
2023-03-23 20:09:00 +08:00
| 'options'
| 'get'
| 'head'
| 'post'
| 'put'
2023-04-14 18:16:39 +08:00
| 'patch'
2023-03-23 20:09:00 +08:00
| 'delete'
| 'trace'
| 'connect';
/**
*
*/
2023-03-28 20:35:40 +08:00
export interface AxiosRequestHeaders extends AnyObject {
2023-04-06 15:16:12 +08:00
/**
*
*/
common?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* options
*/
2023-03-28 20:35:40 +08:00
options?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* get
*/
2023-03-28 20:35:40 +08:00
get?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* head
*/
2023-03-28 20:35:40 +08:00
head?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* post
*/
2023-03-28 20:35:40 +08:00
post?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* put
*/
2023-03-28 20:35:40 +08:00
put?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* delete
*/
2023-03-28 20:35:40 +08:00
delete?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* trace
*/
2023-03-28 20:35:40 +08:00
trace?: AnyObject;
2023-04-06 15:16:12 +08:00
/**
* connect
*/
2023-03-28 20:35:40 +08:00
connect?: AnyObject;
}
2023-03-23 20:09:00 +08:00
/**
*
*/
2023-03-28 20:35:40 +08:00
export interface AxiosRequestFormData extends AnyObject {
2023-04-06 15:16:12 +08:00
/**
*
*/
name: string;
/**
*
*/
2023-03-23 20:09:00 +08:00
filePath: string;
}
/**
*
*/
export type AxiosRequestData =
| string
| AnyObject
| ArrayBuffer
| AxiosRequestFormData;
2023-04-06 15:16:12 +08:00
/**
*
*/
export type AxiosResponseData = number | AxiosAdapterResponseData;
2023-04-09 15:20:10 +08:00
/**
*
*/
export interface AxiosProgressEvent extends AnyObject {
2023-04-15 16:21:54 +08:00
/**
*
2023-04-15 16:21:54 +08:00
*/
2023-03-23 20:09:00 +08:00
progress: number;
}
/**
*
*/
export interface AxiosDownloadProgressEvent extends AxiosProgressEvent {
/**
* Bytes
*/
totalBytesWritten: number;
/**
* Bytes
*/
totalBytesExpectedToWrite: number;
}
/**
*
*/
export interface AxiosDownloadProgressCallback {
(event: AxiosDownloadProgressEvent): void;
}
/**
*
*/
export interface AxiosUploadProgressEvent extends AxiosProgressEvent {
2023-04-15 16:21:54 +08:00
/**
* Bytes
2023-04-15 16:21:54 +08:00
*/
2023-03-23 20:09:00 +08:00
totalBytesSent: number;
2023-04-15 16:21:54 +08:00
/**
* Bytes
2023-04-15 16:21:54 +08:00
*/
2023-03-23 20:09:00 +08:00
totalBytesExpectedToSend: number;
}
/**
*
*/
export interface AxiosUploadProgressCallback {
(event: AxiosUploadProgressEvent): void;
2023-03-23 20:09:00 +08:00
}
/**
*
*/
2023-03-28 20:35:40 +08:00
export interface AxiosRequestConfig
2023-04-09 15:20:10 +08:00
extends Partial<
Omit<AxiosAdapterRequestConfig, 'type' | 'success' | 'fail'>
2023-03-28 20:35:40 +08:00
> {
/**
*
*/
2023-03-23 20:09:00 +08:00
adapter?: AxiosAdapter;
2023-03-28 20:35:40 +08:00
/**
*
*/
2023-03-23 20:09:00 +08:00
baseURL?: string;
2023-04-09 15:20:10 +08:00
/**
* URL
*/
url?: string;
2023-03-28 20:35:40 +08:00
/**
*
*/
params?: AnyObject;
/**
*
*/
2023-04-06 15:16:12 +08:00
data?: AxiosRequestData;
2023-03-28 20:35:40 +08:00
/**
*
*/
headers?: AxiosRequestHeaders;
/**
*
*/
method?: AxiosRequestMethod;
/**
*
*/
2023-03-23 20:09:00 +08:00
cancelToken?: CancelToken;
2023-03-28 20:35:40 +08:00
/**
2023-04-19 12:00:06 +08:00
*
*/
download?: boolean;
/**
*
2023-03-28 20:35:40 +08:00
*/
upload?: boolean;
/**
2023-04-19 12:00:06 +08:00
*
2023-03-28 20:35:40 +08:00
*/
2023-04-19 12:00:06 +08:00
paramsSerializer?: (params?: AnyObject) => string;
/**
*
*/
validateStatus?: (status: number) => boolean;
2023-03-28 20:35:40 +08:00
/**
*
*/
2023-04-09 15:20:10 +08:00
transformRequest?: AxiosTransformer<AxiosRequestData>;
2023-03-28 20:35:40 +08:00
/**
*
*/
2023-04-09 15:20:10 +08:00
transformResponse?: AxiosTransformer<AxiosResponseData>;
2023-03-28 20:35:40 +08:00
/**
*
2023-03-28 20:35:40 +08:00
*/
errorHandler?: (error: unknown) => Promise<AxiosResponse>;
2023-03-28 20:35:40 +08:00
/**
*
2023-03-28 20:35:40 +08:00
*/
onDownloadProgress?: AxiosUploadProgressCallback;
2023-03-28 20:35:40 +08:00
/**
*
2023-03-28 20:35:40 +08:00
*/
onUploadProgress?: AxiosUploadProgressCallback;
2023-03-23 20:09:00 +08:00
}
/**
*
*/
2023-04-09 15:20:10 +08:00
export interface AxiosResponse<
TData extends AxiosResponseData = AxiosResponseData,
2023-04-18 11:14:57 +08:00
> extends AnyObject {
2023-04-06 15:16:12 +08:00
/**
2023-04-18 11:14:57 +08:00
*
2023-04-06 15:16:12 +08:00
*/
2023-04-18 11:14:57 +08:00
status: number;
2023-04-06 15:16:12 +08:00
/**
2023-04-18 11:14:57 +08:00
*
2023-04-06 15:16:12 +08:00
*/
2023-04-18 11:14:57 +08:00
statusText: string;
/**
*
*/
headers: AnyObject;
2023-04-09 15:20:10 +08:00
/**
*
*/
data: TData;
2023-04-18 11:14:57 +08:00
/**
*
*/
config: AxiosRequestConfig;
/**
*
*/
request?: AxiosAdapterPlatformTask;
2023-03-23 20:09:00 +08:00
}
/**
*
*/
2023-04-18 11:14:57 +08:00
export interface AxiosResponseError extends AnyObject {
/**
*
*/
status: number;
/**
*
*/
statusText: string;
/**
*
*/
headers: AnyObject;
/**
*
*/
data: AnyObject;
2023-04-06 15:16:12 +08:00
/**
*
2023-04-06 15:16:12 +08:00
*/
2023-04-05 13:31:48 +08:00
isFail: true;
2023-04-06 15:16:12 +08:00
/**
*
*/
2023-04-18 11:14:57 +08:00
config: AxiosRequestConfig;
2023-04-06 15:16:12 +08:00
/**
*
*/
request?: AxiosAdapterPlatformTask;
2023-03-23 20:09:00 +08:00
}
export interface AxiosRequest {
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
AxiosResponse<TData>
>;
<TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
}
/**
*
*/
export type AxiosRequestMethodFn = <TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosRequestMethodFnWithParams = <TData extends AxiosResponseData>(
url: string,
params?: AnyObject,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosRequestMethodFnWithData = <TData extends AxiosResponseData>(
url: string,
data?: AxiosRequestData,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
export interface AxiosDomainRequestHandler {
(config: AxiosRequestConfig): Promise<AxiosResponse>;
}
/**
* Axios
*/
2023-03-23 20:09:00 +08:00
export interface AxiosConstructor {
new (config: AxiosRequestConfig): Axios;
}
export default class Axios {
#parent?: Axios;
/**
*
*/
defaults: AxiosRequestConfig;
2023-04-06 15:16:12 +08:00
/**
*
*/
interceptors = {
2023-04-06 15:16:12 +08:00
/**
*
*/
2023-03-23 20:09:00 +08:00
request: new InterceptorManager<AxiosRequestConfig>(),
2023-04-06 15:16:12 +08:00
/**
*
*/
2023-03-23 20:09:00 +08:00
response: new InterceptorManager<AxiosResponse>(),
};
/**
*
*/
#middleware = new MiddlewareManager();
2023-03-23 20:09:00 +08:00
/**
* options
*/
options!: AxiosRequestMethodFn;
/**
* get
*/
get!: AxiosRequestMethodFnWithParams;
/**
* head
*/
head!: AxiosRequestMethodFnWithParams;
/**
* post
*/
post!: AxiosRequestMethodFnWithData;
/**
* put
*/
put!: AxiosRequestMethodFnWithData;
/**
* patch
*/
patch!: AxiosRequestMethodFnWithData;
/**
* delete
*/
delete!: AxiosRequestMethodFnWithParams;
/**
* trace
*/
trace!: AxiosRequestMethodFn;
/**
* connect
*/
connect!: AxiosRequestMethodFn;
2023-03-23 20:09:00 +08:00
2023-04-06 15:16:12 +08:00
/**
*
2023-04-06 15:16:12 +08:00
*/
use: MiddlewareUse;
constructor(defaults: AxiosRequestConfig, parent?: Axios) {
this.defaults = defaults;
this.#parent = parent;
2023-04-25 14:28:28 +08:00
this.use = this.#middleware.use;
}
/**
*
*/
request: AxiosRequest = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
config.method = config.method || 'get';
return this.#processRequest(mergeConfig(this.defaults, config));
2023-04-17 19:27:44 +08:00
};
#processRequest(config: AxiosRequestConfig) {
const requestHandler = {
2023-04-25 14:28:28 +08:00
resolved: this.#requestHandler,
};
const errorHandler = {
rejected: config.errorHandler,
};
const chain: (
| Partial<Interceptor<AxiosRequestConfig>>
| Partial<Interceptor<AxiosResponse>>
)[] = [];
2023-03-23 20:09:00 +08:00
2023-04-25 14:28:28 +08:00
this.#eachRequestInterceptors((requestInterceptor) => {
chain.unshift(requestInterceptor);
});
chain.push(requestHandler);
2023-04-25 14:28:28 +08:00
this.#eachResponseInterceptors((responseInterceptor) => {
chain.push(responseInterceptor);
});
chain.push(errorHandler);
return chain.reduce(
(next, { resolved, rejected }) =>
next.then(
// @ts-ignore
resolved,
rejected,
),
Promise.resolve(config),
) as Promise<AxiosResponse>;
2023-04-07 12:39:23 +08:00
}
2023-04-25 14:28:28 +08:00
#eachRequestInterceptors(executor: InterceptorExecutor<AxiosRequestConfig>) {
this.interceptors.request.forEach(executor);
if (this.#parent) {
2023-04-25 14:28:28 +08:00
this.#parent.#eachRequestInterceptors(executor);
}
}
2023-04-25 14:28:28 +08:00
#eachResponseInterceptors(executor: InterceptorExecutor<AxiosResponse>) {
this.interceptors.response.forEach(executor);
if (this.#parent) {
2023-04-25 14:28:28 +08:00
this.#parent.#eachResponseInterceptors(executor);
}
}
#requestHandler = async (config: AxiosRequestConfig) => {
const ctx: MiddlewareContext = {
2023-04-25 14:28:28 +08:00
req: config,
res: null,
};
await this.#wrap(ctx, async () => {
2023-04-25 14:28:28 +08:00
ctx.res = await dispatchRequest(ctx.req);
});
return ctx.res as AxiosResponse;
};
#wrap(ctx: MiddlewareContext, flush: MiddlewareNext): Promise<void> {
2023-04-25 14:28:28 +08:00
if (this.#parent) {
return this.#parent.#wrap(ctx, () => {
return this.#middleware.wrap(ctx, flush);
2023-04-25 14:28:28 +08:00
});
}
return this.#middleware.wrap(ctx, flush);
}
}
for (const method of PLAIN_METHODS) {
Axios.prototype[method] = function processRequestMethod(url, config = {}) {
config.method = method;
return this.request(url, config);
};
}
for (const method of WITH_PARAMS_METHODS) {
Axios.prototype[method] = function processRequestMethodWithParams(
url,
params = {},
config = {},
) {
config.method = method;
config.params = deepMerge(params, config.params ?? {});
return this.request(url, config);
};
}
for (const method of WITH_DATA_METHODS) {
Axios.prototype[method] = function processRequestMethodWithData(
url,
data,
config = {},
) {
config.method = method;
config.data = data;
return this.request(url, config);
};
2023-03-23 20:09:00 +08:00
}