@umijs/plugins
Version:
379 lines (357 loc) • 12.6 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/request.ts
var request_exports = {};
__export(request_exports, {
default: () => request_default
});
module.exports = __toCommonJS(request_exports);
var import_path = require("path");
var import_umi = require("umi");
var import_plugin_utils = require("umi/plugin-utils");
var request_default = (api) => {
api.describe({
key: "request",
config: {
schema: ({ zod }) => {
return zod.object({
// TODO: '' | string 没有找到对应的写法
dataField: zod.string()
}).partial();
}
},
enableBy: api.EnableBy.config
});
api.addRuntimePluginKey(() => ["request"]);
const requestTpl = `
import axios, {
type AxiosInstance,
type AxiosRequestConfig,
type AxiosResponse,
type AxiosError,
} from '{{{axiosPath}}}';
import useUmiRequest, { UseRequestProvider } from '{{{umiRequestPath}}}';
import { ApplyPluginsType } from 'umi';
import { getPluginManager } from '../core/plugin';
import {
BaseOptions,
BasePaginatedOptions,
BaseResult,
CombineService,
LoadMoreFormatReturn,
LoadMoreOptions,
LoadMoreOptionsWithFormat,
LoadMoreParams,
LoadMoreResult,
OptionsWithFormat,
PaginatedFormatReturn,
PaginatedOptionsWithFormat,
PaginatedParams,
PaginatedResult,
} from '{{{umiRequestPath}}}/es/types';
type ResultWithData< T = any > = { {{resultDataType}} [key: string]: any };
function useRequest<
R = any,
P extends any[] = any,
U = any,
UU extends U = any,
>(
service: CombineService<R, P>,
options: OptionsWithFormat<R, P, U, UU>,
): BaseResult<U, P>;
function useRequest<R extends ResultWithData = any, P extends any[] = any>(
service: CombineService<R, P>,
options?: BaseOptions<R{{{resultDataField}}}, P>,
): BaseResult<R{{{resultDataField}}}, P>;
function useRequest<R extends LoadMoreFormatReturn = any, RR = any>(
service: CombineService<RR, LoadMoreParams<R>>,
options: LoadMoreOptionsWithFormat<R, RR>,
): LoadMoreResult<R>;
function useRequest<
R extends ResultWithData<LoadMoreFormatReturn | any> = any,
RR extends R = any,
>(
service: CombineService<R, LoadMoreParams<R{{{resultDataField}}}>>,
options: LoadMoreOptions<RR{{{resultDataField}}}>,
): LoadMoreResult<R{{{resultDataField}}}>;
function useRequest<R = any, Item = any, U extends Item = any>(
service: CombineService<R, PaginatedParams>,
options: PaginatedOptionsWithFormat<R, Item, U>,
): PaginatedResult<Item>;
function useRequest<Item = any, U extends Item = any>(
service: CombineService<
ResultWithData<PaginatedFormatReturn<Item>>,
PaginatedParams
>,
options: BasePaginatedOptions<U>,
): PaginatedResult<Item>;
function useRequest(service: any, options: any = {}) {
return useUmiRequest(service, {
formatResult: {{{formatResult}}},
requestMethod: (requestOptions: any) => {
if (typeof requestOptions === 'string') {
return request(requestOptions);
}
if (typeof requestOptions === 'object') {
const { url, ...rest } = requestOptions;
return request(url, rest);
}
throw new Error('request options error');
},
...options,
});
}
// request 方法 opts 参数的接口
interface IRequestOptions extends AxiosRequestConfig {
skipErrorHandler?: boolean;
requestInterceptors?: IRequestInterceptorTuple[];
responseInterceptors?: IResponseInterceptorTuple[];
[key: string]: any;
}
interface IRequestOptionsWithResponse extends IRequestOptions {
getResponse: true;
}
interface IRequestOptionsWithoutResponse extends IRequestOptions{
getResponse: false;
}
interface IRequest{
<T = any>(url: string, opts: IRequestOptionsWithResponse): Promise<AxiosResponse<T>>;
<T = any>(url: string, opts: IRequestOptionsWithoutResponse): Promise<T>;
<T = any>(url: string, opts: IRequestOptions): Promise<T>; // getResponse 默认是 false, 因此不提供该参数时,只返回 data
<T = any>(url: string): Promise<T>; // 不提供 opts 时,默认使用 'GET' method,并且默认返回 data
}
type RequestError = AxiosError | Error
interface IErrorHandler {
(error: RequestError, opts: IRequestOptions): void;
}
type IRequestInterceptorAxios = (config: RequestOptions) => RequestOptions;
type IRequestInterceptorUmiRequest = (url: string, config : RequestOptions) => { url: string, options: RequestOptions };
type IRequestInterceptor = IRequestInterceptorAxios | IRequestInterceptorUmiRequest;
type IErrorInterceptor = (error: Error) => Promise<Error>;
type IResponseInterceptor = <T = any>(response : AxiosResponse<T>) => AxiosResponse<T> ;
type IRequestInterceptorTuple = [IRequestInterceptor , IErrorInterceptor] | [ IRequestInterceptor ] | IRequestInterceptor
type IResponseInterceptorTuple = [IResponseInterceptor, IErrorInterceptor] | [IResponseInterceptor] | IResponseInterceptor
export interface RequestConfig<T = any> extends AxiosRequestConfig {
errorConfig?: {
errorHandler?: IErrorHandler;
errorThrower?: ( res: T ) => void
};
requestInterceptors?: IRequestInterceptorTuple[];
responseInterceptors?: IResponseInterceptorTuple[];
}
let requestInstance: AxiosInstance;
let config: RequestConfig;
const getConfig = (): RequestConfig => {
if (config) return config;
config = getPluginManager().applyPlugins({
key: 'request',
type: ApplyPluginsType.modify,
initialValue: {},
});
return config;
};
const getRequestInstance = (): AxiosInstance => {
if (requestInstance) return requestInstance;
const config = getConfig();
requestInstance = axios.create(config);
config?.requestInterceptors?.forEach((interceptor) => {
if(interceptor instanceof Array){
requestInstance.interceptors.request.use((config) => {
const { url } = config;
if(interceptor[0].length === 2){
const { url: newUrl, options } = interceptor[0](url, config);
return { ...options, url: newUrl };
}
return interceptor[0](config);
}, interceptor[1]);
} else {
requestInstance.interceptors.request.use((config) => {
const { url } = config;
if(interceptor.length === 2){
const { url: newUrl, options } = interceptor(url, config);
return { ...options, url: newUrl };
}
return interceptor(config);
})
}
});
config?.responseInterceptors?.forEach((interceptor) => {
interceptor instanceof Array ?
requestInstance.interceptors.response.use(interceptor[0], interceptor[1]):
requestInstance.interceptors.response.use(interceptor);
});
// 当响应的数据 success 是 false 的时候,抛出 error 以供 errorHandler 处理。
requestInstance.interceptors.response.use((response) => {
const { data } = response;
if(data?.success === false && config?.errorConfig?.errorThrower){
config.errorConfig.errorThrower(data);
}
return response;
})
return requestInstance;
};
const request: IRequest = (url: string, opts: any = { method: 'GET' }) => {
const requestInstance = getRequestInstance();
const config = getConfig();
const { getResponse = false, requestInterceptors, responseInterceptors } = opts;
const requestInterceptorsToEject = requestInterceptors?.map((interceptor) => {
if(interceptor instanceof Array){
return requestInstance.interceptors.request.use((config) => {
const { url } = config;
if(interceptor[0].length === 2){
const { url: newUrl, options } = interceptor[0](url, config);
return { ...options, url: newUrl };
}
return interceptor[0](config);
}, interceptor[1]);
} else {
return requestInstance.interceptors.request.use((config) => {
const { url } = config;
if(interceptor.length === 2){
const { url: newUrl, options } = interceptor(url, config);
return { ...options, url: newUrl };
}
return interceptor(config);
})
}
});
const responseInterceptorsToEject = responseInterceptors?.map((interceptor) => {
return interceptor instanceof Array ?
requestInstance.interceptors.response.use(interceptor[0], interceptor[1]):
requestInstance.interceptors.response.use(interceptor);
});
return new Promise((resolve, reject)=>{
requestInstance
.request({...opts, url})
.then((res)=>{
requestInterceptorsToEject?.forEach((interceptor) => {
requestInstance.interceptors.request.eject(interceptor);
});
responseInterceptorsToEject?.forEach((interceptor) => {
requestInstance.interceptors.response.eject(interceptor);
});
resolve(getResponse ? res : res.data);
})
.catch((error)=>{
requestInterceptorsToEject?.forEach((interceptor) => {
requestInstance.interceptors.request.eject(interceptor);
});
responseInterceptorsToEject?.forEach((interceptor) => {
requestInstance.interceptors.response.eject(interceptor);
});
try {
const handler =
config?.errorConfig?.errorHandler;
if(handler)
handler(error, opts, config);
} catch (e) {
reject(e);
}
reject(error);
})
})
}
export {
useRequest,
UseRequestProvider,
request,
getRequestInstance,
};
export type {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
AxiosError,
RequestError,
IResponseInterceptor as ResponseInterceptor,
IRequestOptions as RequestOptions,
IRequest as Request,
};
`;
api.onGenerateFiles(() => {
var _a;
const umiRequestPath = (0, import_plugin_utils.winPath)(
(0, import_path.dirname)(require.resolve("@ahooksjs/use-request/package.json"))
);
const axiosPath = (0, import_plugin_utils.winPath)((0, import_path.dirname)(require.resolve("axios/package.json")));
let dataField = (_a = api.config.request) == null ? void 0 : _a.dataField;
if (dataField === void 0)
dataField = "data";
const isEmpty = dataField === "";
const formatResult = isEmpty ? `result => result` : `result => result?.${dataField}`;
const resultDataType = isEmpty ? dataField : `${dataField}?: T;`;
const resultDataField = isEmpty ? dataField : `['${dataField}']`;
api.writeTmpFile({
path: "request.ts",
content: import_plugin_utils.Mustache.render(requestTpl, {
umiRequestPath,
axiosPath,
formatResult,
resultDataType,
resultDataField
})
});
api.writeTmpFile({
path: "types.d.ts",
content: `
export type {
RequestConfig,
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
AxiosError,
RequestError,
ResponseInterceptor,
RequestOptions,
Request } from './request';
`
});
api.writeTmpFile({
path: "index.ts",
content: `
export {
useRequest,
UseRequestProvider,
request,
getRequestInstance,
} from './request';
`
});
api.writeTmpFile({
path: import_umi.RUNTIME_TYPE_FILE_NAME,
content: `
import type { RequestConfig } from './types.d'
export type IRuntimeConfig = {
request?: RequestConfig
};
`
});
});
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {});