diff --git a/.gitignore b/.gitignore index 5e8a253..22286b7 100644 --- a/.gitignore +++ b/.gitignore @@ -106,9 +106,5 @@ dist .idea .vscode -package -types -coverage/ +coverage yarn-error.log -lib -es \ No newline at end of file diff --git a/es/index.js b/es/index.js new file mode 100644 index 0000000..54656db --- /dev/null +++ b/es/index.js @@ -0,0 +1,1242 @@ +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); + return true; + } catch (e) { + return false; + } +} + +function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); +} + +function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; +} + +function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); +} + +function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _iterableToArrayLimit(arr, i) { + if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); +} + +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +var _toString = Object.prototype.toString; +/** + * 对字符串进行编码转换 + * + * @param str 字符串 + */ + +function encode(str) { + return encodeURIComponent(str).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']'); +} +/** + * 是不是一个日期对象 + * + * @param date 判断目标 + */ + +function isDate(date) { + return _toString.call(date) === '[object Date]'; +} +/** + * 是不是一个普通对象 + * + * @param obj 判断目标 + */ + +function isPlainObject(obj) { + return _toString.call(obj) === '[object Object]'; +} +/** + * 深度合并多个对象 + * + * @param objs n 个对象 + */ + +function deepMerge() { + var result = {}; + + function assignValue(key, val) { + // 如果当前结果和当前值都为普通对象 + // 递归进行深度合并 + if (isPlainObject(result[key]) && isPlainObject(val)) { + result[key] = deepMerge(result[key], val); + } // 如果只有当前值为普通对象 + // 直接深拷贝当前值 + else if (isPlainObject(val)) { + result[key] = deepMerge({}, val); + } // 如果都不是普通对象 + // 直接赋值 + else { + result[key] = val; + } + } + + for (var _len = arguments.length, objs = new Array(_len), _key = 0; _key < _len; _key++) { + objs[_key] = arguments[_key]; + } + + objs.forEach(function assignObj(obj) { + Object.entries(obj).forEach(function assignKey(_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + assignValue(key, value); + }); + }); + return result; +} +/** + * 从对象中提取一部分属性 + * + * @param obj 源对象 + * @param keys 需要提取的 key + */ + +function pick(obj) { + var _pick = {}; + + for (var _len2 = arguments.length, keys = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + keys[_key2 - 1] = arguments[_key2]; + } + + keys.forEach(function pickKey(key) { + _pick[key] = obj[key]; + }); + return _pick; +} +/** + * 从对象中剔除一部分属性 + * + * @param obj 源对象 + * @param keys 需要剔除的 key + */ + +function omit(obj) { + var _omit = _objectSpread2({}, obj); + + for (var _len3 = arguments.length, keys = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { + keys[_key3 - 1] = arguments[_key3]; + } + + keys.forEach(function omitKey(key) { + delete _omit[key]; + }); + return _omit; +} + +/** + * 通过请求地址和序列化参数生成新的请求地址 + * + * @param url 请求地址 + * @param serializedParams 序列化参数 + */ + +function generateURL(url, serializedParams) { + // 移除 hash + var hashIndex = url.indexOf('#'); + + if (hashIndex !== -1) { + url = url.slice(0, hashIndex); + } + + if (serializedParams === '') { + return url; + } // 拼接前缀 + + + var prefix = url.indexOf('?') === -1 ? '?' : '&'; + serializedParams = "".concat(prefix).concat(serializedParams); + return "".concat(url).concat(serializedParams); +} +/** + * 默认参数序列化 + * + * @param params 请求参数 + */ + + +function paramsSerialization(params) { + var parts = []; + Object.entries(params).forEach(function encodeKeyValue(_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + if (value === null || value === void 0 || value !== value) { + return; + } // 如果值是一个数组, 则特殊处理 key + + + if (Array.isArray(value)) { + key += '[]'; + } // 转成数组统一处理 + + + var values = [].concat(value); + values.forEach(function (val) { + if (isPlainObject(val)) { + val = JSON.stringify(val); + } else if (isDate(val)) { + val = val.toISOString(); + } + + parts.push("".concat(encode(key), "=").concat(encode(val))); + }); + }); + return parts.join('&'); +} +/** + * 处理 URL 参数 + * + * @param url 请求地址 + * @param params 请求参数 + * @param paramsSerializer 自定义参数序列化 + */ + + +function buildURL(url) { + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var paramsSerializer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : paramsSerialization; + return generateURL(url, paramsSerializer(params)); +} + +/** + * 只取 config2 中的配置 + * + * @param keys + * @param config + * @param config2 + */ + +function onlyFromConfig2(keys, config, config2) { + keys.forEach(function (key) { + if (config2[key] !== void 0) { + config[key] = config2[key]; + } + }); +} +/** + * 优先取 config2 中的配置, config2 中没有就取 config1 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ + + +function priorityFromConfig2(keys, config, config1, config2) { + keys.forEach(function (key) { + if (config2[key] !== void 0) { + config[key] = config2[key]; + } else if (config1[key] !== void 0) { + config[key] = config1[key]; + } + }); +} +/** + * 深度合并配置 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ + + +function deepMergeConfig(keys, config, config1, config2) { + keys.forEach(function (key) { + if (isPlainObject(config2[key])) { + var _config1$key; + + config[key] = deepMerge((_config1$key = config1[key]) !== null && _config1$key !== void 0 ? _config1$key : {}, config2[key]); + } else if (isPlainObject(config1[key])) { + config[key] = deepMerge(config1[key]); + } + }); +} +/** + * 合并 Axios 请求配置 + * + * @param config1 Axios 请求配置1 + * @param config2 Axios 请求配置2 + */ + + +function mergeConfig() { + var config1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var config2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var config = {}; + var onlyFromConfig2Keys = ['url', 'data']; + var priorityFromConfig2Keys = ['adapter', 'baseURL', 'method', 'validateStatus', 'paramsSerializer', 'transformRequest', 'transformResponse', 'errorHandler', 'cancelToken', 'dataType', 'responseType', 'timeout', 'enableHttp2', 'enableQuic', 'enableCache', 'sslVerify']; + var deepMergeConfigKeys = ['headers', 'params']; + onlyFromConfig2(onlyFromConfig2Keys, config, config2); + priorityFromConfig2(priorityFromConfig2Keys, config, config1, config2); + deepMergeConfig(deepMergeConfigKeys, config, config1, config2); + return config; +} + +/** + * 拦截器管理器 + */ +var InterceptorManagerClass = /*#__PURE__*/function () { + function InterceptorManagerClass() { + _classCallCheck(this, InterceptorManagerClass); + + /** + * 生成拦截器 id + */ + this._id = 0; + /** + * 拦截器集合 + */ + + this._interceptors = {}; + } + + _createClass(InterceptorManagerClass, [{ + key: "use", + value: function use(resolved, rejected) { + this._interceptors[++this._id] = { + resolved: resolved, + rejected: rejected + }; + return this._id; + } + }, { + key: "eject", + value: function eject(id) { + delete this._interceptors[id]; + } + }, { + key: "forEach", + value: function forEach(executor, reverse) { + var interceptors = Object.values(this._interceptors); + + if (reverse === 'reverse') { + interceptors = interceptors.reverse(); + } + + interceptors.forEach(executor); + } + }]); + + return InterceptorManagerClass; +}(); + +var CancelClass = /*#__PURE__*/function () { + /** + * @param message 取消信息 + */ + function CancelClass(message) { + _classCallCheck(this, CancelClass); + + this.message = message; + } + + _createClass(CancelClass, [{ + key: "toString", + value: function toString() { + var message = this.message ? ": ".concat(this.message) : ''; + return "Cancel".concat(message); + } + }]); + + return CancelClass; +}(); + +/** + * 是否是取消请求实例 + * + * @param value 判断的值 + */ + +function isCancel(value) { + return value instanceof CancelClass; +} + +/** + * 请求方法转全小写 + * + * @param config Axios 请求配置 + */ +function methodToLowercase() { + var method = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'get'; + return method.toLowerCase(); +} +/** + * 请求方法转全大写 + * + * @param config Axios 请求配置 + */ + +function methodToUppercase() { + var method = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'GET'; + return method.toUpperCase(); +} + +/** + * 拉平请求头 + * + * @param config Axios 请求配置 + */ + +function flattenHeaders(config) { + var _headers$common, _headers$method; + + var headers = config.headers; + + if (headers === void 0) { + return {}; + } + + var method = methodToLowercase(config.method); + return _objectSpread2(_objectSpread2(_objectSpread2({}, (_headers$common = headers.common) !== null && _headers$common !== void 0 ? _headers$common : {}), (_headers$method = headers[method]) !== null && _headers$method !== void 0 ? _headers$method : {}), omit(headers, 'common', 'options', 'get', 'head', 'post', 'put', 'delete', 'trace', 'connect')); +} + +/** + * 转换数据 + * + * @param data 请求数据/响应数据 + * @param headers 请求头/响应头 + * @param transforms 请求数据转换函数/响应数据转换函数 + */ +function transformData(data, headers, transforms) { + if (transforms === void 0) { + return data; + } + + if (!Array.isArray(transforms)) { + transforms = [transforms]; + } + + transforms.forEach(function (transform) { + data = transform(data, headers); + }); + return data; +} + +/** + * 检查是否是一个绝对 URL + * + * xxx:// 或者 "//" 开头, 视为绝对地址 + * + * @param url 需要检查的 URL + */ +function isAbsoluteURL(url) { + return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); +} + +/** + * 拼接 baseURL 和 url 获得完整的 URL + * + * combineURL('1/2///','////3/4') => '1/2/3/4' + */ +function combineURL(baseURL, url) { + return "".concat(baseURL.replace(/\/*$/, ''), "/").concat(url.replace(/^\/*/, '')); +} + +/** + * 根据配置中的 baseURL 和 url 和 params 生成完整 URL + * + * @param config Axios 请求配置 + */ + +function transformURL(config) { + var _config$baseURL = config.baseURL, + baseURL = _config$baseURL === void 0 ? '' : _config$baseURL, + _config$url = config.url, + url = _config$url === void 0 ? '' : _config$url; + var fullURL = isAbsoluteURL(url) ? url : combineURL(baseURL, url); + return buildURL(fullURL, config.params, config.paramsSerializer); +} +/** + * Axios 请求配置转换成各大平台通用请求配置 + * + * 抹平差异 + * + * @param config Axios 请求配置 + */ + + +function transformRequest(config) { + return _objectSpread2({ + url: transformURL(config), + method: methodToUppercase(config.method), + header: config.headers + }, pick(config, 'data', 'headers', 'dataType', 'responseType', 'timeout', 'enableHttp2', 'enableQuic', 'enableCache', 'sslVerify')); +} + +/** + * 各大平台通用响应体转成 Axios 响应体 + * + * 抹平差异 + * + * @param response 通用响应体 + * @param config Axios 请求配置 + */ + +function transformResponse(response, config) { + var _ref, _response$statusCode, _ref2, _response$header; + + var status = (_ref = (_response$statusCode = response.statusCode) !== null && _response$statusCode !== void 0 ? _response$statusCode : response.status) !== null && _ref !== void 0 ? _ref : 400; + var headers = (_ref2 = (_response$header = response.header) !== null && _response$header !== void 0 ? _response$header : response.headers) !== null && _ref2 !== void 0 ? _ref2 : {}; + var statusText = status === 200 ? 'OK' : status === 400 ? 'Bad Adapter' : ''; + return _objectSpread2({ + status: status, + statusText: statusText, + headers: headers, + config: config + }, pick(response, 'data', 'cookies', 'profile')); +} + +/** + * AxiosError 继承自 Error + */ +var AxiosErrorClass = /*#__PURE__*/function (_Error) { + _inherits(AxiosErrorClass, _Error); + + var _super = _createSuper(AxiosErrorClass); + + /** + * @param message 错误信息 + * @param config Axios 请求配置 + * @param request 通用请求配置 + * @param response Axios 响应体 + */ + function AxiosErrorClass(message, config, request, response) { + var _this; + + _classCallCheck(this, AxiosErrorClass); + + _this = _super.call(this, message); + _this.config = config; + _this.request = request; + _this.response = response; + _this.isAxiosError = true; // 修复继承系统自带类 prototype 设置失败的问题 + + Object.setPrototypeOf(_assertThisInitialized(_this), AxiosErrorClass.prototype); + return _this; + } + + return AxiosErrorClass; +}( /*#__PURE__*/_wrapNativeSuper(Error)); +/** + * 创建 AxiosError 的工厂方法 + * + * 返回一个新的 AxiosError 对象 + * + * @param message 错误信息 + * @param config Axios 请求配置 + * @param request 通用请求配置 + * @param response Axios 响应体 + */ + + +function createError(message, config, request, response) { + return new AxiosErrorClass(message, config, request, response); +} + +/** + * 请求函数 + * + * @param config Axios 请求配置 + */ + +function request(config) { + return new Promise(function dispatchAdapter(resolve, reject) { + var adapter = config.adapter, + cancelToken = config.cancelToken; + var requestConfig = transformRequest(config); + /** + * 捕获错误 + * + * @param message 错误信息 + * @param response Axios 响应体 + */ + + function catchError(message, response) { + if (typeof message !== 'string') { + message = '配置不正确或者网络异常'; + } + + reject(createError(message, config, requestConfig, response)); + } + + if (adapter === void 0) { + catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台'); + return; + } + /** + * 效验状态码 + * + * @param res 请求结果 + */ + + + function handleResponse(res) { + var response = transformResponse(res, config); + + if (config.validateStatus === void 0 || config.validateStatus(response.status)) { + resolve(response); + } else { + catchError("\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801\u4E3A ".concat(response.status), response); + } + } // 使用适配器发送请求 + + + var task = adapter(_objectSpread2(_objectSpread2({}, requestConfig), {}, { + success: handleResponse, + fail: catchError + })); // 如果存在取消令牌 + // 则调用取消令牌里的 listener 监听用户的取消操作 + + if (cancelToken !== void 0) { + cancelToken.listener.then(function onCanceled(reason) { + if (task !== void 0) { + task.abort(); + } + + reject(reason); + }); + } + }); +} + +/** + * 如果已经取消, 则抛出取消对象 + * + * @param config Axios 请求配置 + */ + +function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } +} +/** + * 发送请求 + * + * @param config Axios 请求配置 + */ + + +function dispatchRequest(config) { + var _config$data; + + throwIfCancellationRequested(config); + config.headers = flattenHeaders(config); + config.data = transformData((_config$data = config.data) !== null && _config$data !== void 0 ? _config$data : {}, config.headers, config.transformRequest); + + function onResolved(response) { + throwIfCancellationRequested(config); + response.data = transformData(response.data, response.headers, config.transformResponse); + return response; + } + + function onRejected(reason) { + var _config$errorHandler, _config$errorHandler2; + + if (!isCancel(reason)) { + throwIfCancellationRequested(config); + + if (reason.response !== void 0) { + reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse); + } + } + + return (_config$errorHandler = (_config$errorHandler2 = config.errorHandler) === null || _config$errorHandler2 === void 0 ? void 0 : _config$errorHandler2.call(config, reason)) !== null && _config$errorHandler !== void 0 ? _config$errorHandler : Promise.reject(reason); + } + + return request(config).then(onResolved, onRejected); +} + +var AxiosClass = /*#__PURE__*/function () { + /** + * @param defaults 自定义默认配置 + */ + function AxiosClass() { + var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, AxiosClass); + + this.defaults = defaults; + this.interceptors = { + request: new InterceptorManagerClass(), + response: new InterceptorManagerClass() + }; + } + + _createClass(AxiosClass, [{ + key: "getUri", + value: function getUri(config) { + var _mergeConfig = mergeConfig(this.defaults, config), + _mergeConfig$url = _mergeConfig.url, + url = _mergeConfig$url === void 0 ? '' : _mergeConfig$url, + params = _mergeConfig.params, + paramsSerializer = _mergeConfig.paramsSerializer; + + return buildURL(url, params, paramsSerializer).replace(/^\?/, ''); + } + }, { + key: "request", + value: function request(config) { + var requestConfig = mergeConfig(this.defaults, config); + var promiseRequest = Promise.resolve(requestConfig); // 执行请求拦截器 + + this.interceptors.request.forEach(function executor(_ref) { + var resolved = _ref.resolved, + rejected = _ref.rejected; + promiseRequest = promiseRequest.then(resolved, rejected); + }, 'reverse'); // 发送请求 + + var promiseResponse = promiseRequest.then(dispatchRequest); // 执行响应拦截器 + + this.interceptors.response.forEach(function executor(_ref2) { + var resolved = _ref2.resolved, + rejected = _ref2.rejected; + promiseResponse = promiseResponse.then(resolved, rejected); + }); + return promiseResponse; + } + }, { + key: "options", + value: function options(url, config) { + return this._requestMethodWithoutParams('options', url, void 0, config); + } + }, { + key: "get", + value: function get(url, params, config) { + return this._requestMethodWithoutParams('get', url, params, config); + } + }, { + key: "head", + value: function head(url, params, config) { + return this._requestMethodWithoutParams('head', url, params, config); + } + }, { + key: "post", + value: function post(url, data, config) { + return this._requestMethodWithoutData('post', url, data, config); + } + }, { + key: "put", + value: function put(url, data, config) { + return this._requestMethodWithoutData('put', url, data, config); + } + }, { + key: "delete", + value: function _delete(url, params, config) { + return this._requestMethodWithoutParams('delete', url, params, config); + } + }, { + key: "trace", + value: function trace(url, config) { + return this._requestMethodWithoutParams('trace', url, void 0, config); + } + }, { + key: "connect", + value: function connect(url, config) { + return this._requestMethodWithoutParams('connect', url, void 0, config); + } + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + + }, { + key: "_requestMethodWithoutParams", + value: function _requestMethodWithoutParams(method, url, params) { + var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return this.request(_objectSpread2(_objectSpread2({}, config), {}, { + method: method, + url: url, + params: params + })); + } + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param data 请求数据 + * @param config 额外配置 + */ + + }, { + key: "_requestMethodWithoutData", + value: function _requestMethodWithoutData(method, url, data) { + var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return this.request(_objectSpread2(_objectSpread2({}, config), {}, { + method: method, + url: url, + data: data + })); + } + }]); + + return AxiosClass; +}(); + +var CancelTokenClass = /*#__PURE__*/function () { + function CancelTokenClass(executor) { + var _this = this; + + _classCallCheck(this, CancelTokenClass); + + var action; + this.listener = new Promise(function (resolve) { + action = function action(message) { + // 防止重复取消 + if (_this._reason) { + return; + } + + _this._reason = new CancelClass(message); + resolve(_this._reason); + }; + }); + executor(action); + } + + _createClass(CancelTokenClass, [{ + key: "throwIfRequested", + value: function throwIfRequested() { + if (this._reason) { + throw this._reason; + } + } + /** + * 返回一个 CancelTokenSource + * + * CancelTokenSource.token 是一个 CancelToken 对象 + * + * CancelTokenSource.cancel 是一个 CancelAction 函数 + * + * 调用 CancelTokenSource.cancel('这里可以填写您的错误信息') + * + * 取消请求 CancelTokenSource.token + */ + + }], [{ + key: "source", + value: function source() { + var cancel; + var token = new CancelTokenClass(function executor(action) { + cancel = action; + }); + return { + token: token, + cancel: cancel + }; + } + }]); + + return CancelTokenClass; +}(); + +/** + * 自适应当前平台 + */ +function adaptive() { + var stack = [function () { + return uni.request; + }, function () { + return wx.request; + }, function () { + return my.request; + }, function () { + return swan.request; + }, function () { + return tt.request; + }, function () { + return qq.request; + }]; + var adapter; + + while (stack.length !== 0 && adapter === void 0) { + try { + adapter = stack.shift()(); + } catch (err) {} + } + + return adapter; +} + +var defaults = { + /** + * 适配器 + */ + adapter: adaptive(), + + /** + * 请求方法 + */ + method: 'get', + + /** + * 请求头 + */ + headers: { + common: { + Accept: 'application/json, test/plain, */*' + }, + options: {}, + get: {}, + head: {}, + post: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + }, + put: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + }, + "delete": {}, + trace: {}, + connect: {} + }, + + /** + * 状态码效验 + * + * @param status 状态码 + */ + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + }, + + /** + * 超时时间 + */ + timeout: 10000, + + /** + * 响应数据格式 + */ + dataType: 'json', + + /** + * 响应数据类型 + */ + responseType: 'text', + + /** + * 开启 http2 + */ + enableHttp2: false, + + /** + * 开启 quic + */ + enableQuic: false, + + /** + * 开启 cache + */ + enableCache: false, + + /** + * 验证 ssl 证书 + */ + sslVerify: true +}; + +/** + * 创建一个新的 Axios 实例 + * + * 返回一个 Axios 实例增强 + */ + +function createInstance(defaults) { + var instance = new AxiosClass(defaults); + /** + * 支持重载的 axios 函数 + */ + + function axios(url) { + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + // 调用方式一处理请求配置 + if (typeof url !== 'string') { + config = url; + } // 调用方式二处理请求配置 + else { + config = _objectSpread2(_objectSpread2({}, config), {}, { + url: url + }); + } + + return instance.request(config); + } // instance 的属性合并到 axios 函数中 + + + Object.assign(axios, instance); // instance 的方法合并到 axios 函数中 + + Object.setPrototypeOf(axios, Object.getPrototypeOf(instance)); + return axios; +} +/** + * Axios 实例拓展 + */ + + +var axios = createInstance(defaults); // 添加 create 工厂方法 + +axios.create = function create() { + var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return createInstance(mergeConfig(axios.defaults, defaults)); +}; // 添加 Axios 类 + + +axios.Axios = AxiosClass; // 添加 CancelToken 类 + +axios.CancelToken = CancelTokenClass; // 添加 检查错误是否来自取消请求 方法 + +axios.isCancel = isCancel; + +export default axios; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..2a141bb --- /dev/null +++ b/lib/index.js @@ -0,0 +1,1244 @@ +'use strict'; + +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} + +function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } +} + +function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) _setPrototypeOf(subClass, superClass); +} + +function _getPrototypeOf(o) { + _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + return _getPrototypeOf(o); +} + +function _setPrototypeOf(o, p) { + _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + return _setPrototypeOf(o, p); +} + +function _isNativeReflectConstruct() { + if (typeof Reflect === "undefined" || !Reflect.construct) return false; + if (Reflect.construct.sham) return false; + if (typeof Proxy === "function") return true; + + try { + Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); + return true; + } catch (e) { + return false; + } +} + +function _construct(Parent, args, Class) { + if (_isNativeReflectConstruct()) { + _construct = Reflect.construct; + } else { + _construct = function _construct(Parent, args, Class) { + var a = [null]; + a.push.apply(a, args); + var Constructor = Function.bind.apply(Parent, a); + var instance = new Constructor(); + if (Class) _setPrototypeOf(instance, Class.prototype); + return instance; + }; + } + + return _construct.apply(null, arguments); +} + +function _isNativeFunction(fn) { + return Function.toString.call(fn).indexOf("[native code]") !== -1; +} + +function _wrapNativeSuper(Class) { + var _cache = typeof Map === "function" ? new Map() : undefined; + + _wrapNativeSuper = function _wrapNativeSuper(Class) { + if (Class === null || !_isNativeFunction(Class)) return Class; + + if (typeof Class !== "function") { + throw new TypeError("Super expression must either be null or a function"); + } + + if (typeof _cache !== "undefined") { + if (_cache.has(Class)) return _cache.get(Class); + + _cache.set(Class, Wrapper); + } + + function Wrapper() { + return _construct(Class, arguments, _getPrototypeOf(this).constructor); + } + + Wrapper.prototype = Object.create(Class.prototype, { + constructor: { + value: Wrapper, + enumerable: false, + writable: true, + configurable: true + } + }); + return _setPrototypeOf(Wrapper, Class); + }; + + return _wrapNativeSuper(Class); +} + +function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; +} + +function _possibleConstructorReturn(self, call) { + if (call && (typeof call === "object" || typeof call === "function")) { + return call; + } + + return _assertThisInitialized(self); +} + +function _createSuper(Derived) { + var hasNativeReflectConstruct = _isNativeReflectConstruct(); + + return function _createSuperInternal() { + var Super = _getPrototypeOf(Derived), + result; + + if (hasNativeReflectConstruct) { + var NewTarget = _getPrototypeOf(this).constructor; + + result = Reflect.construct(Super, arguments, NewTarget); + } else { + result = Super.apply(this, arguments); + } + + return _possibleConstructorReturn(this, result); + }; +} + +function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); +} + +function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; +} + +function _iterableToArrayLimit(arr, i) { + if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; + var _arr = []; + var _n = true; + var _d = false; + var _e = undefined; + + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i["return"] != null) _i["return"](); + } finally { + if (_d) throw _e; + } + } + + return _arr; +} + +function _unsupportedIterableToArray(o, minLen) { + if (!o) return; + if (typeof o === "string") return _arrayLikeToArray(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === "Object" && o.constructor) n = o.constructor.name; + if (n === "Map" || n === "Set") return Array.from(o); + if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); +} + +function _arrayLikeToArray(arr, len) { + if (len == null || len > arr.length) len = arr.length; + + for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; + + return arr2; +} + +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} + +var _toString = Object.prototype.toString; +/** + * 对字符串进行编码转换 + * + * @param str 字符串 + */ + +function encode(str) { + return encodeURIComponent(str).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']'); +} +/** + * 是不是一个日期对象 + * + * @param date 判断目标 + */ + +function isDate(date) { + return _toString.call(date) === '[object Date]'; +} +/** + * 是不是一个普通对象 + * + * @param obj 判断目标 + */ + +function isPlainObject(obj) { + return _toString.call(obj) === '[object Object]'; +} +/** + * 深度合并多个对象 + * + * @param objs n 个对象 + */ + +function deepMerge() { + var result = {}; + + function assignValue(key, val) { + // 如果当前结果和当前值都为普通对象 + // 递归进行深度合并 + if (isPlainObject(result[key]) && isPlainObject(val)) { + result[key] = deepMerge(result[key], val); + } // 如果只有当前值为普通对象 + // 直接深拷贝当前值 + else if (isPlainObject(val)) { + result[key] = deepMerge({}, val); + } // 如果都不是普通对象 + // 直接赋值 + else { + result[key] = val; + } + } + + for (var _len = arguments.length, objs = new Array(_len), _key = 0; _key < _len; _key++) { + objs[_key] = arguments[_key]; + } + + objs.forEach(function assignObj(obj) { + Object.entries(obj).forEach(function assignKey(_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + assignValue(key, value); + }); + }); + return result; +} +/** + * 从对象中提取一部分属性 + * + * @param obj 源对象 + * @param keys 需要提取的 key + */ + +function pick(obj) { + var _pick = {}; + + for (var _len2 = arguments.length, keys = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + keys[_key2 - 1] = arguments[_key2]; + } + + keys.forEach(function pickKey(key) { + _pick[key] = obj[key]; + }); + return _pick; +} +/** + * 从对象中剔除一部分属性 + * + * @param obj 源对象 + * @param keys 需要剔除的 key + */ + +function omit(obj) { + var _omit = _objectSpread2({}, obj); + + for (var _len3 = arguments.length, keys = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { + keys[_key3 - 1] = arguments[_key3]; + } + + keys.forEach(function omitKey(key) { + delete _omit[key]; + }); + return _omit; +} + +/** + * 通过请求地址和序列化参数生成新的请求地址 + * + * @param url 请求地址 + * @param serializedParams 序列化参数 + */ + +function generateURL(url, serializedParams) { + // 移除 hash + var hashIndex = url.indexOf('#'); + + if (hashIndex !== -1) { + url = url.slice(0, hashIndex); + } + + if (serializedParams === '') { + return url; + } // 拼接前缀 + + + var prefix = url.indexOf('?') === -1 ? '?' : '&'; + serializedParams = "".concat(prefix).concat(serializedParams); + return "".concat(url).concat(serializedParams); +} +/** + * 默认参数序列化 + * + * @param params 请求参数 + */ + + +function paramsSerialization(params) { + var parts = []; + Object.entries(params).forEach(function encodeKeyValue(_ref) { + var _ref2 = _slicedToArray(_ref, 2), + key = _ref2[0], + value = _ref2[1]; + + if (value === null || value === void 0 || value !== value) { + return; + } // 如果值是一个数组, 则特殊处理 key + + + if (Array.isArray(value)) { + key += '[]'; + } // 转成数组统一处理 + + + var values = [].concat(value); + values.forEach(function (val) { + if (isPlainObject(val)) { + val = JSON.stringify(val); + } else if (isDate(val)) { + val = val.toISOString(); + } + + parts.push("".concat(encode(key), "=").concat(encode(val))); + }); + }); + return parts.join('&'); +} +/** + * 处理 URL 参数 + * + * @param url 请求地址 + * @param params 请求参数 + * @param paramsSerializer 自定义参数序列化 + */ + + +function buildURL(url) { + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var paramsSerializer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : paramsSerialization; + return generateURL(url, paramsSerializer(params)); +} + +/** + * 只取 config2 中的配置 + * + * @param keys + * @param config + * @param config2 + */ + +function onlyFromConfig2(keys, config, config2) { + keys.forEach(function (key) { + if (config2[key] !== void 0) { + config[key] = config2[key]; + } + }); +} +/** + * 优先取 config2 中的配置, config2 中没有就取 config1 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ + + +function priorityFromConfig2(keys, config, config1, config2) { + keys.forEach(function (key) { + if (config2[key] !== void 0) { + config[key] = config2[key]; + } else if (config1[key] !== void 0) { + config[key] = config1[key]; + } + }); +} +/** + * 深度合并配置 + * + * @param keys + * @param config + * @param config1 + * @param config2 + */ + + +function deepMergeConfig(keys, config, config1, config2) { + keys.forEach(function (key) { + if (isPlainObject(config2[key])) { + var _config1$key; + + config[key] = deepMerge((_config1$key = config1[key]) !== null && _config1$key !== void 0 ? _config1$key : {}, config2[key]); + } else if (isPlainObject(config1[key])) { + config[key] = deepMerge(config1[key]); + } + }); +} +/** + * 合并 Axios 请求配置 + * + * @param config1 Axios 请求配置1 + * @param config2 Axios 请求配置2 + */ + + +function mergeConfig() { + var config1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var config2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var config = {}; + var onlyFromConfig2Keys = ['url', 'data']; + var priorityFromConfig2Keys = ['adapter', 'baseURL', 'method', 'validateStatus', 'paramsSerializer', 'transformRequest', 'transformResponse', 'errorHandler', 'cancelToken', 'dataType', 'responseType', 'timeout', 'enableHttp2', 'enableQuic', 'enableCache', 'sslVerify']; + var deepMergeConfigKeys = ['headers', 'params']; + onlyFromConfig2(onlyFromConfig2Keys, config, config2); + priorityFromConfig2(priorityFromConfig2Keys, config, config1, config2); + deepMergeConfig(deepMergeConfigKeys, config, config1, config2); + return config; +} + +/** + * 拦截器管理器 + */ +var InterceptorManagerClass = /*#__PURE__*/function () { + function InterceptorManagerClass() { + _classCallCheck(this, InterceptorManagerClass); + + /** + * 生成拦截器 id + */ + this._id = 0; + /** + * 拦截器集合 + */ + + this._interceptors = {}; + } + + _createClass(InterceptorManagerClass, [{ + key: "use", + value: function use(resolved, rejected) { + this._interceptors[++this._id] = { + resolved: resolved, + rejected: rejected + }; + return this._id; + } + }, { + key: "eject", + value: function eject(id) { + delete this._interceptors[id]; + } + }, { + key: "forEach", + value: function forEach(executor, reverse) { + var interceptors = Object.values(this._interceptors); + + if (reverse === 'reverse') { + interceptors = interceptors.reverse(); + } + + interceptors.forEach(executor); + } + }]); + + return InterceptorManagerClass; +}(); + +var CancelClass = /*#__PURE__*/function () { + /** + * @param message 取消信息 + */ + function CancelClass(message) { + _classCallCheck(this, CancelClass); + + this.message = message; + } + + _createClass(CancelClass, [{ + key: "toString", + value: function toString() { + var message = this.message ? ": ".concat(this.message) : ''; + return "Cancel".concat(message); + } + }]); + + return CancelClass; +}(); + +/** + * 是否是取消请求实例 + * + * @param value 判断的值 + */ + +function isCancel(value) { + return value instanceof CancelClass; +} + +/** + * 请求方法转全小写 + * + * @param config Axios 请求配置 + */ +function methodToLowercase() { + var method = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'get'; + return method.toLowerCase(); +} +/** + * 请求方法转全大写 + * + * @param config Axios 请求配置 + */ + +function methodToUppercase() { + var method = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'GET'; + return method.toUpperCase(); +} + +/** + * 拉平请求头 + * + * @param config Axios 请求配置 + */ + +function flattenHeaders(config) { + var _headers$common, _headers$method; + + var headers = config.headers; + + if (headers === void 0) { + return {}; + } + + var method = methodToLowercase(config.method); + return _objectSpread2(_objectSpread2(_objectSpread2({}, (_headers$common = headers.common) !== null && _headers$common !== void 0 ? _headers$common : {}), (_headers$method = headers[method]) !== null && _headers$method !== void 0 ? _headers$method : {}), omit(headers, 'common', 'options', 'get', 'head', 'post', 'put', 'delete', 'trace', 'connect')); +} + +/** + * 转换数据 + * + * @param data 请求数据/响应数据 + * @param headers 请求头/响应头 + * @param transforms 请求数据转换函数/响应数据转换函数 + */ +function transformData(data, headers, transforms) { + if (transforms === void 0) { + return data; + } + + if (!Array.isArray(transforms)) { + transforms = [transforms]; + } + + transforms.forEach(function (transform) { + data = transform(data, headers); + }); + return data; +} + +/** + * 检查是否是一个绝对 URL + * + * xxx:// 或者 "//" 开头, 视为绝对地址 + * + * @param url 需要检查的 URL + */ +function isAbsoluteURL(url) { + return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); +} + +/** + * 拼接 baseURL 和 url 获得完整的 URL + * + * combineURL('1/2///','////3/4') => '1/2/3/4' + */ +function combineURL(baseURL, url) { + return "".concat(baseURL.replace(/\/*$/, ''), "/").concat(url.replace(/^\/*/, '')); +} + +/** + * 根据配置中的 baseURL 和 url 和 params 生成完整 URL + * + * @param config Axios 请求配置 + */ + +function transformURL(config) { + var _config$baseURL = config.baseURL, + baseURL = _config$baseURL === void 0 ? '' : _config$baseURL, + _config$url = config.url, + url = _config$url === void 0 ? '' : _config$url; + var fullURL = isAbsoluteURL(url) ? url : combineURL(baseURL, url); + return buildURL(fullURL, config.params, config.paramsSerializer); +} +/** + * Axios 请求配置转换成各大平台通用请求配置 + * + * 抹平差异 + * + * @param config Axios 请求配置 + */ + + +function transformRequest(config) { + return _objectSpread2({ + url: transformURL(config), + method: methodToUppercase(config.method), + header: config.headers + }, pick(config, 'data', 'headers', 'dataType', 'responseType', 'timeout', 'enableHttp2', 'enableQuic', 'enableCache', 'sslVerify')); +} + +/** + * 各大平台通用响应体转成 Axios 响应体 + * + * 抹平差异 + * + * @param response 通用响应体 + * @param config Axios 请求配置 + */ + +function transformResponse(response, config) { + var _ref, _response$statusCode, _ref2, _response$header; + + var status = (_ref = (_response$statusCode = response.statusCode) !== null && _response$statusCode !== void 0 ? _response$statusCode : response.status) !== null && _ref !== void 0 ? _ref : 400; + var headers = (_ref2 = (_response$header = response.header) !== null && _response$header !== void 0 ? _response$header : response.headers) !== null && _ref2 !== void 0 ? _ref2 : {}; + var statusText = status === 200 ? 'OK' : status === 400 ? 'Bad Adapter' : ''; + return _objectSpread2({ + status: status, + statusText: statusText, + headers: headers, + config: config + }, pick(response, 'data', 'cookies', 'profile')); +} + +/** + * AxiosError 继承自 Error + */ +var AxiosErrorClass = /*#__PURE__*/function (_Error) { + _inherits(AxiosErrorClass, _Error); + + var _super = _createSuper(AxiosErrorClass); + + /** + * @param message 错误信息 + * @param config Axios 请求配置 + * @param request 通用请求配置 + * @param response Axios 响应体 + */ + function AxiosErrorClass(message, config, request, response) { + var _this; + + _classCallCheck(this, AxiosErrorClass); + + _this = _super.call(this, message); + _this.config = config; + _this.request = request; + _this.response = response; + _this.isAxiosError = true; // 修复继承系统自带类 prototype 设置失败的问题 + + Object.setPrototypeOf(_assertThisInitialized(_this), AxiosErrorClass.prototype); + return _this; + } + + return AxiosErrorClass; +}( /*#__PURE__*/_wrapNativeSuper(Error)); +/** + * 创建 AxiosError 的工厂方法 + * + * 返回一个新的 AxiosError 对象 + * + * @param message 错误信息 + * @param config Axios 请求配置 + * @param request 通用请求配置 + * @param response Axios 响应体 + */ + + +function createError(message, config, request, response) { + return new AxiosErrorClass(message, config, request, response); +} + +/** + * 请求函数 + * + * @param config Axios 请求配置 + */ + +function request(config) { + return new Promise(function dispatchAdapter(resolve, reject) { + var adapter = config.adapter, + cancelToken = config.cancelToken; + var requestConfig = transformRequest(config); + /** + * 捕获错误 + * + * @param message 错误信息 + * @param response Axios 响应体 + */ + + function catchError(message, response) { + if (typeof message !== 'string') { + message = '配置不正确或者网络异常'; + } + + reject(createError(message, config, requestConfig, response)); + } + + if (adapter === void 0) { + catchError('平台适配失败,您需要参阅文档使用自定义适配器手动适配当前平台'); + return; + } + /** + * 效验状态码 + * + * @param res 请求结果 + */ + + + function handleResponse(res) { + var response = transformResponse(res, config); + + if (config.validateStatus === void 0 || config.validateStatus(response.status)) { + resolve(response); + } else { + catchError("\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801\u4E3A ".concat(response.status), response); + } + } // 使用适配器发送请求 + + + var task = adapter(_objectSpread2(_objectSpread2({}, requestConfig), {}, { + success: handleResponse, + fail: catchError + })); // 如果存在取消令牌 + // 则调用取消令牌里的 listener 监听用户的取消操作 + + if (cancelToken !== void 0) { + cancelToken.listener.then(function onCanceled(reason) { + if (task !== void 0) { + task.abort(); + } + + reject(reason); + }); + } + }); +} + +/** + * 如果已经取消, 则抛出取消对象 + * + * @param config Axios 请求配置 + */ + +function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } +} +/** + * 发送请求 + * + * @param config Axios 请求配置 + */ + + +function dispatchRequest(config) { + var _config$data; + + throwIfCancellationRequested(config); + config.headers = flattenHeaders(config); + config.data = transformData((_config$data = config.data) !== null && _config$data !== void 0 ? _config$data : {}, config.headers, config.transformRequest); + + function onResolved(response) { + throwIfCancellationRequested(config); + response.data = transformData(response.data, response.headers, config.transformResponse); + return response; + } + + function onRejected(reason) { + var _config$errorHandler, _config$errorHandler2; + + if (!isCancel(reason)) { + throwIfCancellationRequested(config); + + if (reason.response !== void 0) { + reason.response.data = transformData(reason.response.data, reason.response.headers, config.transformResponse); + } + } + + return (_config$errorHandler = (_config$errorHandler2 = config.errorHandler) === null || _config$errorHandler2 === void 0 ? void 0 : _config$errorHandler2.call(config, reason)) !== null && _config$errorHandler !== void 0 ? _config$errorHandler : Promise.reject(reason); + } + + return request(config).then(onResolved, onRejected); +} + +var AxiosClass = /*#__PURE__*/function () { + /** + * @param defaults 自定义默认配置 + */ + function AxiosClass() { + var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, AxiosClass); + + this.defaults = defaults; + this.interceptors = { + request: new InterceptorManagerClass(), + response: new InterceptorManagerClass() + }; + } + + _createClass(AxiosClass, [{ + key: "getUri", + value: function getUri(config) { + var _mergeConfig = mergeConfig(this.defaults, config), + _mergeConfig$url = _mergeConfig.url, + url = _mergeConfig$url === void 0 ? '' : _mergeConfig$url, + params = _mergeConfig.params, + paramsSerializer = _mergeConfig.paramsSerializer; + + return buildURL(url, params, paramsSerializer).replace(/^\?/, ''); + } + }, { + key: "request", + value: function request(config) { + var requestConfig = mergeConfig(this.defaults, config); + var promiseRequest = Promise.resolve(requestConfig); // 执行请求拦截器 + + this.interceptors.request.forEach(function executor(_ref) { + var resolved = _ref.resolved, + rejected = _ref.rejected; + promiseRequest = promiseRequest.then(resolved, rejected); + }, 'reverse'); // 发送请求 + + var promiseResponse = promiseRequest.then(dispatchRequest); // 执行响应拦截器 + + this.interceptors.response.forEach(function executor(_ref2) { + var resolved = _ref2.resolved, + rejected = _ref2.rejected; + promiseResponse = promiseResponse.then(resolved, rejected); + }); + return promiseResponse; + } + }, { + key: "options", + value: function options(url, config) { + return this._requestMethodWithoutParams('options', url, void 0, config); + } + }, { + key: "get", + value: function get(url, params, config) { + return this._requestMethodWithoutParams('get', url, params, config); + } + }, { + key: "head", + value: function head(url, params, config) { + return this._requestMethodWithoutParams('head', url, params, config); + } + }, { + key: "post", + value: function post(url, data, config) { + return this._requestMethodWithoutData('post', url, data, config); + } + }, { + key: "put", + value: function put(url, data, config) { + return this._requestMethodWithoutData('put', url, data, config); + } + }, { + key: "delete", + value: function _delete(url, params, config) { + return this._requestMethodWithoutParams('delete', url, params, config); + } + }, { + key: "trace", + value: function trace(url, config) { + return this._requestMethodWithoutParams('trace', url, void 0, config); + } + }, { + key: "connect", + value: function connect(url, config) { + return this._requestMethodWithoutParams('connect', url, void 0, config); + } + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + + }, { + key: "_requestMethodWithoutParams", + value: function _requestMethodWithoutParams(method, url, params) { + var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return this.request(_objectSpread2(_objectSpread2({}, config), {}, { + method: method, + url: url, + params: params + })); + } + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param data 请求数据 + * @param config 额外配置 + */ + + }, { + key: "_requestMethodWithoutData", + value: function _requestMethodWithoutData(method, url, data) { + var config = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + return this.request(_objectSpread2(_objectSpread2({}, config), {}, { + method: method, + url: url, + data: data + })); + } + }]); + + return AxiosClass; +}(); + +var CancelTokenClass = /*#__PURE__*/function () { + function CancelTokenClass(executor) { + var _this = this; + + _classCallCheck(this, CancelTokenClass); + + var action; + this.listener = new Promise(function (resolve) { + action = function action(message) { + // 防止重复取消 + if (_this._reason) { + return; + } + + _this._reason = new CancelClass(message); + resolve(_this._reason); + }; + }); + executor(action); + } + + _createClass(CancelTokenClass, [{ + key: "throwIfRequested", + value: function throwIfRequested() { + if (this._reason) { + throw this._reason; + } + } + /** + * 返回一个 CancelTokenSource + * + * CancelTokenSource.token 是一个 CancelToken 对象 + * + * CancelTokenSource.cancel 是一个 CancelAction 函数 + * + * 调用 CancelTokenSource.cancel('这里可以填写您的错误信息') + * + * 取消请求 CancelTokenSource.token + */ + + }], [{ + key: "source", + value: function source() { + var cancel; + var token = new CancelTokenClass(function executor(action) { + cancel = action; + }); + return { + token: token, + cancel: cancel + }; + } + }]); + + return CancelTokenClass; +}(); + +/** + * 自适应当前平台 + */ +function adaptive() { + var stack = [function () { + return uni.request; + }, function () { + return wx.request; + }, function () { + return my.request; + }, function () { + return swan.request; + }, function () { + return tt.request; + }, function () { + return qq.request; + }]; + var adapter; + + while (stack.length !== 0 && adapter === void 0) { + try { + adapter = stack.shift()(); + } catch (err) {} + } + + return adapter; +} + +var defaults = { + /** + * 适配器 + */ + adapter: adaptive(), + + /** + * 请求方法 + */ + method: 'get', + + /** + * 请求头 + */ + headers: { + common: { + Accept: 'application/json, test/plain, */*' + }, + options: {}, + get: {}, + head: {}, + post: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + }, + put: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' + }, + "delete": {}, + trace: {}, + connect: {} + }, + + /** + * 状态码效验 + * + * @param status 状态码 + */ + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + }, + + /** + * 超时时间 + */ + timeout: 10000, + + /** + * 响应数据格式 + */ + dataType: 'json', + + /** + * 响应数据类型 + */ + responseType: 'text', + + /** + * 开启 http2 + */ + enableHttp2: false, + + /** + * 开启 quic + */ + enableQuic: false, + + /** + * 开启 cache + */ + enableCache: false, + + /** + * 验证 ssl 证书 + */ + sslVerify: true +}; + +/** + * 创建一个新的 Axios 实例 + * + * 返回一个 Axios 实例增强 + */ + +function createInstance(defaults) { + var instance = new AxiosClass(defaults); + /** + * 支持重载的 axios 函数 + */ + + function axios(url) { + var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + // 调用方式一处理请求配置 + if (typeof url !== 'string') { + config = url; + } // 调用方式二处理请求配置 + else { + config = _objectSpread2(_objectSpread2({}, config), {}, { + url: url + }); + } + + return instance.request(config); + } // instance 的属性合并到 axios 函数中 + + + Object.assign(axios, instance); // instance 的方法合并到 axios 函数中 + + Object.setPrototypeOf(axios, Object.getPrototypeOf(instance)); + return axios; +} +/** + * Axios 实例拓展 + */ + + +var axios = createInstance(defaults); // 添加 create 工厂方法 + +axios.create = function create() { + var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + return createInstance(mergeConfig(axios.defaults, defaults)); +}; // 添加 Axios 类 + + +axios.Axios = AxiosClass; // 添加 CancelToken 类 + +axios.CancelToken = CancelTokenClass; // 添加 检查错误是否来自取消请求 方法 + +axios.isCancel = isCancel; + +module.exports = axios; diff --git a/types/adaptive.d.ts b/types/adaptive.d.ts new file mode 100644 index 0000000..06873fd --- /dev/null +++ b/types/adaptive.d.ts @@ -0,0 +1,5 @@ +import { Adapter } from './types'; +/** + * 自适应当前平台 + */ +export default function adaptive(): Adapter | undefined; diff --git a/types/axios.d.ts b/types/axios.d.ts new file mode 100644 index 0000000..7326c25 --- /dev/null +++ b/types/axios.d.ts @@ -0,0 +1,6 @@ +import { AxiosInstance } from './types'; +/** + * Axios 实例拓展 + */ +declare const axios: AxiosInstance; +export default axios; diff --git a/types/cancel/Cancel.d.ts b/types/cancel/Cancel.d.ts new file mode 100644 index 0000000..4867d24 --- /dev/null +++ b/types/cancel/Cancel.d.ts @@ -0,0 +1,9 @@ +import { Cancel } from '../types'; +export default class CancelClass implements Cancel { + message?: string | undefined; + /** + * @param message 取消信息 + */ + constructor(message?: string | undefined); + toString(): string; +} diff --git a/types/cancel/CancelToken.d.ts b/types/cancel/CancelToken.d.ts new file mode 100644 index 0000000..70557be --- /dev/null +++ b/types/cancel/CancelToken.d.ts @@ -0,0 +1,23 @@ +import { CancelToken, CancelExecutor, CancelTokenSource } from '../types'; +import Cancel from './Cancel'; +export default class CancelTokenClass implements CancelToken { + /** + * 取消请求 + */ + private _reason?; + listener: Promise; + constructor(executor: CancelExecutor); + throwIfRequested(): void; + /** + * 返回一个 CancelTokenSource + * + * CancelTokenSource.token 是一个 CancelToken 对象 + * + * CancelTokenSource.cancel 是一个 CancelAction 函数 + * + * 调用 CancelTokenSource.cancel('这里可以填写您的错误信息') + * + * 取消请求 CancelTokenSource.token + */ + static source(): CancelTokenSource; +} diff --git a/types/cancel/isCancel.d.ts b/types/cancel/isCancel.d.ts new file mode 100644 index 0000000..364e6e2 --- /dev/null +++ b/types/cancel/isCancel.d.ts @@ -0,0 +1,7 @@ +import Cancel from './Cancel'; +/** + * 是否是取消请求实例 + * + * @param value 判断的值 + */ +export default function isCancel(value: unknown): value is Cancel; diff --git a/types/core/Axios.d.ts b/types/core/Axios.d.ts new file mode 100644 index 0000000..62b1496 --- /dev/null +++ b/types/core/Axios.d.ts @@ -0,0 +1,37 @@ +import { Params, Data, Interceptors, AxiosRequestConfig, AxiosResponse, Axios } from '../types'; +export default class AxiosClass implements Axios { + defaults: AxiosRequestConfig; + interceptors: Interceptors; + /** + * @param defaults 自定义默认配置 + */ + constructor(defaults?: AxiosRequestConfig); + getUri(config: AxiosRequestConfig): string; + request(config: AxiosRequestConfig): Promise>; + options(url: string, config?: AxiosRequestConfig): Promise>; + get(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + head(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + post(url: string, data?: Data, config?: AxiosRequestConfig): Promise>; + put(url: string, data?: Data, config?: AxiosRequestConfig): Promise>; + delete(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + trace(url: string, config?: AxiosRequestConfig): Promise>; + connect(url: string, config?: AxiosRequestConfig): Promise>; + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + private _requestMethodWithoutParams; + /** + * 合并配置后发送 HTTP 请求 + * + * @param method 请求方法 + * @param url 请求地址 + * @param data 请求数据 + * @param config 额外配置 + */ + private _requestMethodWithoutData; +} diff --git a/types/core/InterceptorManager.d.ts b/types/core/InterceptorManager.d.ts new file mode 100644 index 0000000..0805229 --- /dev/null +++ b/types/core/InterceptorManager.d.ts @@ -0,0 +1,17 @@ +import { InterceptorResolved, InterceptorRejected, InterceptorExecutor, InterceptorManager } from '../types'; +/** + * 拦截器管理器 + */ +export default class InterceptorManagerClass implements InterceptorManager { + /** + * 生成拦截器 id + */ + private _id; + /** + * 拦截器集合 + */ + private _interceptors; + use(resolved: InterceptorResolved, rejected?: InterceptorRejected): number; + eject(id: number): void; + forEach(executor: InterceptorExecutor, reverse?: 'reverse'): void; +} diff --git a/types/core/createError.d.ts b/types/core/createError.d.ts new file mode 100644 index 0000000..b6a1f2f --- /dev/null +++ b/types/core/createError.d.ts @@ -0,0 +1,12 @@ +import { AxiosRequestConfig, RequestConfig, AxiosResponse, AxiosError } from '../types'; +/** + * 创建 AxiosError 的工厂方法 + * + * 返回一个新的 AxiosError 对象 + * + * @param message 错误信息 + * @param config Axios 请求配置 + * @param request 通用请求配置 + * @param response Axios 响应体 + */ +export default function createError(message: string, config: AxiosRequestConfig, request: RequestConfig, response?: AxiosResponse): AxiosError; diff --git a/types/core/dispatchRequest.d.ts b/types/core/dispatchRequest.d.ts new file mode 100644 index 0000000..d89d9af --- /dev/null +++ b/types/core/dispatchRequest.d.ts @@ -0,0 +1,7 @@ +import { AxiosRequestConfig, AxiosResponse } from '../types'; +/** + * 发送请求 + * + * @param config Axios 请求配置 + */ +export default function dispatchRequest(config: AxiosRequestConfig): Promise; diff --git a/types/core/flattenHeaders.d.ts b/types/core/flattenHeaders.d.ts new file mode 100644 index 0000000..89de838 --- /dev/null +++ b/types/core/flattenHeaders.d.ts @@ -0,0 +1,7 @@ +import { Headers, AxiosRequestConfig } from '../types'; +/** + * 拉平请求头 + * + * @param config Axios 请求配置 + */ +export default function flattenHeaders(config: AxiosRequestConfig): Headers; diff --git a/types/core/mergeConfig.d.ts b/types/core/mergeConfig.d.ts new file mode 100644 index 0000000..c9dfa74 --- /dev/null +++ b/types/core/mergeConfig.d.ts @@ -0,0 +1,8 @@ +import { AxiosRequestConfig } from '../types'; +/** + * 合并 Axios 请求配置 + * + * @param config1 Axios 请求配置1 + * @param config2 Axios 请求配置2 + */ +export default function mergeConfig(config1?: AxiosRequestConfig, config2?: AxiosRequestConfig): AxiosRequestConfig; diff --git a/types/core/request.d.ts b/types/core/request.d.ts new file mode 100644 index 0000000..c5e9a5e --- /dev/null +++ b/types/core/request.d.ts @@ -0,0 +1,7 @@ +import { AxiosRequestConfig, AxiosResponse } from '../types'; +/** + * 请求函数 + * + * @param config Axios 请求配置 + */ +export default function request(config: AxiosRequestConfig): Promise; diff --git a/types/core/transformData.d.ts b/types/core/transformData.d.ts new file mode 100644 index 0000000..3dafb15 --- /dev/null +++ b/types/core/transformData.d.ts @@ -0,0 +1,9 @@ +import { Data, Headers, TransformData } from '../types'; +/** + * 转换数据 + * + * @param data 请求数据/响应数据 + * @param headers 请求头/响应头 + * @param transforms 请求数据转换函数/响应数据转换函数 + */ +export default function transformData(data: Data, headers: Headers, transforms?: TransformData | TransformData[]): Data; diff --git a/types/core/transformMethod.d.ts b/types/core/transformMethod.d.ts new file mode 100644 index 0000000..019245f --- /dev/null +++ b/types/core/transformMethod.d.ts @@ -0,0 +1,13 @@ +import { AliasMethod, AdapterMethod, Method } from '../types'; +/** + * 请求方法转全小写 + * + * @param config Axios 请求配置 + */ +export declare function methodToLowercase(method?: Method): AliasMethod; +/** + * 请求方法转全大写 + * + * @param config Axios 请求配置 + */ +export declare function methodToUppercase(method?: Method): AdapterMethod; diff --git a/types/core/transformRequest.d.ts b/types/core/transformRequest.d.ts new file mode 100644 index 0000000..299b979 --- /dev/null +++ b/types/core/transformRequest.d.ts @@ -0,0 +1,9 @@ +import { AxiosRequestConfig, RequestConfig } from '../types'; +/** + * Axios 请求配置转换成各大平台通用请求配置 + * + * 抹平差异 + * + * @param config Axios 请求配置 + */ +export default function transformRequest(config: AxiosRequestConfig): RequestConfig; diff --git a/types/core/transformResponse.d.ts b/types/core/transformResponse.d.ts new file mode 100644 index 0000000..ee2446b --- /dev/null +++ b/types/core/transformResponse.d.ts @@ -0,0 +1,10 @@ +import { AxiosRequestConfig, AxiosResponse, Response } from '../types'; +/** + * 各大平台通用响应体转成 Axios 响应体 + * + * 抹平差异 + * + * @param response 通用响应体 + * @param config Axios 请求配置 + */ +export default function transformResponse(response: Response, config: AxiosRequestConfig): AxiosResponse; diff --git a/types/defaults.d.ts b/types/defaults.d.ts new file mode 100644 index 0000000..ab86472 --- /dev/null +++ b/types/defaults.d.ts @@ -0,0 +1,3 @@ +import { AxiosRequestConfig } from './types'; +declare const defaults: AxiosRequestConfig; +export default defaults; diff --git a/types/helpers/buildURL.d.ts b/types/helpers/buildURL.d.ts new file mode 100644 index 0000000..e3597bd --- /dev/null +++ b/types/helpers/buildURL.d.ts @@ -0,0 +1,16 @@ +import { AnyObject, Params } from '../types'; +/** + * 默认参数序列化 + * + * @param params 请求参数 + */ +declare function paramsSerialization(params: AnyObject): string; +/** + * 处理 URL 参数 + * + * @param url 请求地址 + * @param params 请求参数 + * @param paramsSerializer 自定义参数序列化 + */ +export default function buildURL(url: string, params?: Params, paramsSerializer?: typeof paramsSerialization): string; +export {}; diff --git a/types/helpers/combineURL.d.ts b/types/helpers/combineURL.d.ts new file mode 100644 index 0000000..e4156df --- /dev/null +++ b/types/helpers/combineURL.d.ts @@ -0,0 +1,6 @@ +/** + * 拼接 baseURL 和 url 获得完整的 URL + * + * combineURL('1/2///','////3/4') => '1/2/3/4' + */ +export default function combineURL(baseURL: string, url: string): string; diff --git a/types/helpers/isAbsoluteURL.d.ts b/types/helpers/isAbsoluteURL.d.ts new file mode 100644 index 0000000..5444e4d --- /dev/null +++ b/types/helpers/isAbsoluteURL.d.ts @@ -0,0 +1,8 @@ +/** + * 检查是否是一个绝对 URL + * + * xxx:// 或者 "//" 开头, 视为绝对地址 + * + * @param url 需要检查的 URL + */ +export default function isAbsoluteURL(url: string): boolean; diff --git a/types/helpers/utils.d.ts b/types/helpers/utils.d.ts new file mode 100644 index 0000000..5c09ae4 --- /dev/null +++ b/types/helpers/utils.d.ts @@ -0,0 +1,39 @@ +import { AnyObject } from '../types'; +/** + * 对字符串进行编码转换 + * + * @param str 字符串 + */ +export declare function encode(str: string): string; +/** + * 是不是一个日期对象 + * + * @param date 判断目标 + */ +export declare function isDate(date: unknown): date is Date; +/** + * 是不是一个普通对象 + * + * @param obj 判断目标 + */ +export declare function isPlainObject(obj: unknown): obj is Record; +/** + * 深度合并多个对象 + * + * @param objs n 个对象 + */ +export declare function deepMerge(...objs: Record[]): Record; +/** + * 从对象中提取一部分属性 + * + * @param obj 源对象 + * @param keys 需要提取的 key + */ +export declare function pick(obj: T, ...keys: K[]): Pick; +/** + * 从对象中剔除一部分属性 + * + * @param obj 源对象 + * @param keys 需要剔除的 key + */ +export declare function omit(obj: T, ...keys: K[]): Omit; diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 0000000..53c6af9 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,3 @@ +import axios from './axios'; +export * from './types'; +export default axios; diff --git a/types/types.d.ts b/types/types.d.ts new file mode 100644 index 0000000..3846406 --- /dev/null +++ b/types/types.d.ts @@ -0,0 +1,596 @@ +/** + * 任意值对象 + */ +export declare interface AnyObject { + [x: string]: T; +} +/** + * 请求方法 + */ +export declare type AdapterMethod = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'; +/** + * 请求方法别名 + */ +export declare type AliasMethod = 'options' | 'get' | 'head' | 'post' | 'put' | 'delete' | 'trace' | 'connect'; +/** + * Axios 请求方法 + */ +export declare type Method = AliasMethod | AdapterMethod; +/** + * Axios 参数 + */ +export declare type Params = AnyObject; +/** + * Axios 数据 + */ +export declare type Data = string | AnyObject | ArrayBuffer; +/** + * Axios 头 + */ +export declare interface Headers extends Partial>> { + /** + * 自定义配置 + */ + [x: string]: AnyObject | string | undefined; +} +/** + * 通用请求配置 + */ +export declare interface RequestConfig { + /** + * 接口地址 + */ + url: string; + /** + * HTTP 请求方法 + */ + method: AdapterMethod; + /** + * 请求数据 + */ + data: Data; + /** + * 请求头 同 headers + */ + header: AnyObject; + /** + * 请求头 同 header + */ + headers: AnyObject; + /** + * 返回的数据格式 + */ + dataType?: 'json' | '其他'; + /** + * 响应的数据类型 + */ + responseType?: 'text' | 'arraybuffer'; + /** + * 超时时间 + */ + timeout?: number; + /** + * 开启 http2 + */ + enableHttp2?: boolean; + /** + * 开启 quic + */ + enableQuic?: boolean; + /** + * 开启 cache + */ + enableCache?: boolean; + /** + * 验证 ssl 证书 + */ + sslVerify?: boolean; +} +/** + * 通用响应体 + */ +export declare interface Response { + /** + * 响应状态码 + */ + statusCode?: number; + /** + * 响应状态码 + */ + status?: number; + /** + * 响应头 Headers + */ + header?: AnyObject; + /** + * 响应头 Headers + */ + headers?: Headers; + /** + * 响应数据 + */ + data: Data; + /** + * 开发者服务器返回的 cookies,格式为字符串数组 + */ + cookies?: string[]; + /** + * 网络请求过程中一些关键时间点的耗时信息 + */ + profile?: AnyObject; +} +/** + * 适配器请求配置 + */ +export declare interface AdapterRequestConfig extends RequestConfig { + /** + * 成功的响应函数 + */ + success: (res: Response) => void; + /** + * 失败的响应函数 + */ + fail: (err: unknown) => void; +} +/** + * 适配器请求任务 + */ +export declare interface AdapterRequestTask { + /** + * 取消请求 + */ + abort(): void; +} +/** + * 适配器 + */ +export declare interface Adapter { + (config: AdapterRequestConfig): AdapterRequestTask | void; +} +/** + * 平台 + */ +export declare interface Platform { + request: Adapter; +} +/** + * 转换数据函数 + */ +export declare interface TransformData { + (data: Data, headers: Headers): Data; +} +/** + * 错误处理程序 + */ +export declare interface ErrorHandler { + (error: any): Promise | any; +} +/** + * Axios 请求配置 + */ +export declare interface AxiosRequestConfig { + /** + * 自定义适配器 + */ + adapter?: Adapter; + /** + * 基础地址 + */ + baseURL?: string; + /** + * 请求地址 + */ + url?: string; + /** + * 请求方法 + */ + method?: Method; + /** + * 请求参数 + */ + params?: Params; + /** + * 请求数据 + */ + data?: Data; + /** + * 请求头 + */ + headers?: Headers; + /** + * 自定义合法状态码 + */ + validateStatus?: (status: number) => boolean; + /** + * 自定义参数序列化 + */ + paramsSerializer?: (params?: AnyObject) => string; + /** + * 转换请求数据 + */ + transformRequest?: TransformData | TransformData[]; + /** + * 转换响应数据 + */ + transformResponse?: TransformData | TransformData[]; + /** + * 自定义错误处理 + */ + errorHandler?: ErrorHandler; + /** + * 取消令牌 + */ + cancelToken?: CancelToken; + /** + * 超时时间 + */ + timeout?: number; + /** + * 响应数据格式 + */ + dataType?: 'json' | '其他'; + /** + * 响应数据类型 + */ + responseType?: 'text' | 'arraybuffer'; + /** + * 开启 http2 + */ + enableHttp2?: boolean; + /** + * 开启 quic + */ + enableQuic?: boolean; + /** + * 开启 cache + */ + enableCache?: boolean; + /** + * 验证 ssl 证书 + */ + sslVerify?: boolean; +} +/** + * Axios 响应体 + */ +export declare interface AxiosResponse { + /** + * 状态码 + */ + status: number; + /** + * 状态文本 + */ + statusText: string; + /** + * 服务端返回的数据 + */ + data: T; + /** + * 响应头 + */ + headers: Headers; + /** + * Axios 请求配置 + */ + config: AxiosRequestConfig; + /** + * 开发者服务器返回的 cookies,格式为字符串数组 + */ + cookies?: string[]; + /** + * 网络请求过程中一些关键时间点的耗时信息 + */ + profile?: AnyObject; +} +/** + * 拦截器成功的回调函数 + */ +export declare interface InterceptorResolved { + (value: T): Promise | T; +} +/** + * 拦截器失败的回调函数 + */ +export declare interface InterceptorRejected { + (error: any): any; +} +/** + * 拦截器 + */ +export declare interface Interceptor { + /** + * 拦截器成功的回调函数 + */ + resolved: InterceptorResolved; + /** + * 拦截器失败的回调函数 + */ + rejected?: InterceptorRejected; +} +/** + * 拦截器执行器 + */ +export declare interface InterceptorExecutor { + (interceptor: Interceptor): void; +} +/** + * 拦截器管理器 + */ +export declare interface InterceptorManager { + [x: string]: any; + /** + * 添加拦截器 + * + * @param resolved 成功的回调函数 + * @param rejected 失败的回调函数 + */ + use(resolved: InterceptorResolved, rejected?: InterceptorRejected): number; + /** + * 删除拦截器 + * + * @param id 拦截器 id + */ + eject(id: number): void; + /** + * 遍历所有拦截器 + * + * @param executor 拦截器执行器 + * @param reverse 是否倒序遍历 + */ + forEach(executor: InterceptorExecutor, reverse?: 'reverse'): void; +} +/** + * Axios 拦截器 + */ +export declare interface Interceptors { + /** + * request 请求拦截器 + */ + request: InterceptorManager; + /** + * response 响应拦截器 + */ + response: InterceptorManager; +} +/** + * Axios 实例 + */ +export declare interface Axios { + /** + * 默认配置 + */ + defaults: AxiosRequestConfig; + /** + * Axios 拦截器 + */ + interceptors: Interceptors; + /** + * 根据配置中的 url 和 params 生成一个 URI + * + * @param config 请求配置 + */ + getUri(config: AxiosRequestConfig): string; + /** + * 发送 HTTP 请求 + * + * @param config 请求配置 + */ + request(config: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 OPTIONS + * + * @param url 请求地址 + * @param config 额外配置 + */ + options(url: string, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 GET + * + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + get(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 HEAD + * + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + head(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 POST + * + * @param url 请求地址 + * @param data 请求数据 + * @param config 额外配置 + */ + post(url: string, data?: Data, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 PUT + * + * @param url 请求地址 + * @param data 请求数据 + * @param config 额外配置 + */ + put(url: string, data?: Data, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 DELETE + * + * @param url 请求地址 + * @param params 请求参数 + * @param config 额外配置 + */ + delete(url: string, params?: Params, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 TRACE + * + * @param url 请求地址 + * @param config 额外配置 + */ + trace(url: string, config?: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 CONNECT + * + * @param url 请求地址 + * @param config 额外配置 + */ + connect(url: string, config?: AxiosRequestConfig): Promise>; +} +/** + * Axios 类接口 + */ +export declare interface AxiosConstructor { + new (config?: AxiosRequestConfig): Axios; +} +/** + * AxiosError 类继承自 Error + */ +export declare interface AxiosError extends Error { + /** + * 是 Axios 错误 + */ + isAxiosError: boolean; + /** + * 请求配置 + */ + config: AxiosRequestConfig; + /** + * 通用请求配置 + */ + request: RequestConfig; + /** + * Axios 响应体 + */ + response?: AxiosResponse; +} +/** + * 取消请求 + */ +export declare interface Cancel { + /** + * 取消信息 + */ + message?: string; + /** + * 序列化 + */ + toString(): string; +} +/** + * 取消请求类接口 + */ +export declare interface CancelConstructor { + new (message?: string): Cancel; +} +/** + * 取消操作 + */ +export declare interface CancelAction { + (message?: string): void; +} +/** + * 取消操作执行器 + */ +export declare interface CancelExecutor { + (cancel: CancelAction): void; +} +/** + * 取消令牌 + */ +export declare interface CancelToken { + /** + * 取消时被触发 + */ + listener: Promise; + /** + * 如果已经取消, 则抛出取消对象 + */ + throwIfRequested(): void; +} +/** + * 取消令牌 source + */ +export declare interface CancelTokenSource { + /** + * 取消令牌 + */ + token: CancelToken; + /** + * 取消操作 + */ + cancel: CancelAction; +} +/** + * 取消令牌类接口 + */ +export declare interface CancelTokenConstructor { + new (executor: CancelExecutor): CancelToken; + /** + * 返回一个 CancelTokenSource + * + * CancelTokenSource.token 是一个 CancelToken 对象 + * + * CancelTokenSource.cancel 是一个 CancelAction 函数 + * + * 调用 CancelTokenSource.cancel('这里可以填写您的错误信息') + * + * 取消请求 CancelTokenSource.token + */ + source(): CancelTokenSource; +} +/** + * Axios 实例基础拓展 + * + * * 支持两种函数调用方式 + */ +export declare interface AxiosBaseInstance extends Axios { + /** + * 发送 HTTP 请求 + * + * 调用方式一 + * + * @param config 请求配置 + */ + (config: AxiosRequestConfig): Promise>; + /** + * 发送 HTTP 请求 + * + * 调用方式二 + * + * @param url 请求地址 + * @param config 额外配置 + */ + (url: string, config?: AxiosRequestConfig): Promise>; +} +/** + * Axios 实例拓展 + * + * * 支持两种函数调用方式 + * + * * 同时拓展了一些静态属性和方法 + */ +export declare interface AxiosInstance extends AxiosBaseInstance { + /** + * 创建 Axios 实例基础拓展 + * + * @param defaults 自定义默认配置 + */ + create(defaults?: AxiosRequestConfig): AxiosBaseInstance; + /** + * Axios 类 + */ + Axios: AxiosConstructor; + /** + * 取消令牌 类 + */ + CancelToken: CancelTokenConstructor; + /** + * 检查错误是否来自取消请求 + * + * @param value 判断的值 + */ + isCancel: (value: any) => boolean; +} diff --git a/yarn.lock b/yarn.lock index d628b60..8edb6d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -673,16 +673,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-runtime@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.5.tgz#3b39b7b24830e0c2d8ff7a4489fe5cf99fbace86" - integrity sha512-tV4V/FjElJ9lQtyjr5xD2IFFbgY46r7EeVu5a8CpEKT5laheHKSlFeHjpkPppW3PqzGLAuv5k2qZX5LgVZIX5w== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - resolve "^1.8.1" - semver "^5.5.1" - "@babel/plugin-transform-shorthand-properties@^7.10.4": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" @@ -838,21 +828,6 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typescript" "^7.10.4" -"@babel/runtime-corejs3@^7.11.2": - version "7.11.2" - resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz#02c3029743150188edeb66541195f54600278419" - integrity sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.10.5": - version "7.10.5" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" - integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/runtime@^7.8.4": version "7.11.0" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.0.tgz#f10245877042a815e07f7e693faff0ae9d3a2aac" @@ -1910,11 +1885,6 @@ core-js-compat@^3.6.2: browserslist "^4.8.5" semver "7.0.0" -core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2287,11 +2257,6 @@ estraverse@^5.1.0: resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== -estree-walker@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" - integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== - estree-walker@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" @@ -3706,7 +3671,7 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -magic-string@^0.25.2, magic-string@^0.25.3: +magic-string@^0.25.2: version "0.25.7" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -4404,7 +4369,7 @@ resolve@1.15.1: dependencies: path-parse "^1.0.6" -resolve@^1.10.0, resolve@^1.11.0, resolve@^1.17.0, resolve@^1.3.2, resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.11.0, resolve@^1.17.0, resolve@^1.3.2: version "1.17.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== @@ -4438,22 +4403,6 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" -rollup-plugin-inject@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz#e4233855bfba6c0c12a312fd6649dff9a13ee9f4" - integrity sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w== - dependencies: - estree-walker "^0.6.1" - magic-string "^0.25.3" - rollup-pluginutils "^2.8.1" - -rollup-plugin-node-polyfills@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd" - integrity sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA== - dependencies: - rollup-plugin-inject "^3.0.0" - rollup-plugin-typescript2@^0.27.1: version "0.27.1" resolved "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.27.1.tgz#4f27193408a8f040139eed3e3db7b0c7f3668200" @@ -4465,13 +4414,6 @@ rollup-plugin-typescript2@^0.27.1: resolve "1.15.1" tslib "1.11.2" -rollup-pluginutils@^2.8.1: - version "2.8.2" - resolved "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" - integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== - dependencies: - estree-walker "^0.6.1" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -4538,7 +4480,7 @@ semver-regex@^2.0.0: resolved "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==