UNPKG

@ifed/umi-preset

Version:
337 lines (311 loc) 11.2 kB
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 pluginKey = "request"; var request_default = (api) => { api.describe({ key: pluginKey, // 对应.umirc.ts中的配置项 config: { schema: ({ zod }) => { return zod.object({ // TODO: '' | string 没有找到对应的写法 dataField: zod.string() }).partial(); } }, enableBy: api.EnableBy.config }); api.addRuntimePluginKey(() => [pluginKey]); const requestTpl = ` import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosResponse, type AxiosError, } from '{{{axiosPath}}}'; import { default as useUmiRequest, clearCache } from '{{{umiRequestPath}}}/es/useRequest'; import { ApplyPluginsType } from 'umi'; import { getPluginManager } from '../core/plugin'; function get(obj: any, path: string, defaultValue?: any): any { // 检查 obj 是否为对象 if (typeof obj !== 'object' || obj === null) { return defaultValue; } // 将 path 字符串转换为数组格式 const pathArr = path.split('.'); // 遍历路径数组 for (let i = 0; i < pathArr.length; i++) { const key = pathArr[i]; // 检查当前 key 是否存在于 obj 中 if (obj.hasOwnProperty(key)) { obj = obj[key]; } else { // 如果不存在,则返回默认值 return defaultValue; } } return obj; } function useRequest(service: any, options: any = {}) { return useUmiRequest(service, { ...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 get(response, '{{{dataField}}}'); }) 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, clearCache, request, getRequestInstance, axios }; 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("ahooks/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"; api.writeTmpFile({ path: "request.ts", content: import_plugin_utils.Mustache.render(requestTpl, { umiRequestPath, axiosPath, dataField }) }); 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, clearCache, request, getRequestInstance, axios } from './request'; ` }); api.writeTmpFile({ path: import_umi.RUNTIME_TYPE_FILE_NAME, content: ` import type { RequestConfig } from './types.d' export type IRuntimeConfig = { request?: RequestConfig }; ` }); }); api.addRuntimePluginKey(() => ["demo"]); };