UNPKG

fastlion-amis

Version:

一种MIS页面生成工具

514 lines (513 loc) 20.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.normalizeApiResponseData = exports.clearApiCache = exports.setApiCache = exports.getApiCache = exports.isSameApi = exports.isEffectiveApi = exports.isValidApi = exports.isApiOutdated = exports.jsonpFetcher = exports.wrapAdaptor = exports.wrapFetcher = exports.responseAdaptor = exports.str2AsyncFunction = exports.str2function = exports.buildApi = exports.normalizeApi = void 0; var tslib_1 = require("tslib"); var omit_1 = (0, tslib_1.__importDefault)(require("lodash/omit")); var tpl_builtin_1 = require("./tpl-builtin"); var tpl_1 = require("./tpl"); var helper_1 = require("./helper"); var isPlainObject_1 = (0, tslib_1.__importDefault)(require("lodash/isPlainObject")); var debug_1 = require("./debug"); var rSchema = /(?:^|raw\:)(get|post|put|delete|patch|options|head|jsonp):/i; var apiCaches = []; var isIE = !!document.documentMode; function normalizeApi(api, defaultMethod) { if (defaultMethod === void 0) { defaultMethod = 'get'; } if (typeof api === 'string') { var method = rSchema.test(api) ? RegExp.$1 : ''; method && (api = api.replace(method + ':', '')); api = { method: (method || defaultMethod), url: api }; } else { api = (0, tslib_1.__assign)({}, api); } return api; } exports.normalizeApi = normalizeApi; function buildApi(api, data, options) { if (options === void 0) { options = {}; } api = normalizeApi(api, options.method); var autoAppend = options.autoAppend, ignoreData = options.ignoreData, rest = (0, tslib_1.__rest)(options, ["autoAppend", "ignoreData"]); api.config = (0, tslib_1.__assign)({}, rest); api.method = (api.method || options.method || 'get').toLowerCase(); if (api.headers) { api.headers = (0, tpl_builtin_1.dataMapping)(api.headers, data, undefined, false); } if (api.requestAdaptor && typeof api.requestAdaptor === 'string') { api.requestAdaptor = str2function(api.requestAdaptor, 'api'); } if (api.adaptor && typeof api.adaptor === 'string') { api.adaptor = str2function(api.adaptor, 'payload', 'response', 'api'); } if (!data) { return api; } else if (data instanceof FormData || data instanceof Blob || data instanceof ArrayBuffer) { api.data = data; return api; } var raw = (api.url = api.url || ''); var idx = api.url.indexOf('?'); if (~idx) { var hashIdx = api.url.indexOf('#'); var params = (0, helper_1.qsparse)(api.url.substring(idx + 1, ~hashIdx && hashIdx > idx ? hashIdx : undefined)); api.url = (0, tpl_builtin_1.tokenize)(api.url.substring(0, idx + 1), data, '| url_encode') + (0, helper_1.qsstringify)((api.query = (0, tpl_builtin_1.dataMapping)(params, data, undefined, api.convertKeyToPath))) + (~hashIdx && hashIdx > idx ? api.url.substring(hashIdx) : ''); } else { api.url = (0, tpl_builtin_1.tokenize)(api.url, data, '| url_encode'); } if (ignoreData) { return api; } if (api.data) { api.body = api.data = (0, tpl_builtin_1.dataMapping)(api.data, data, undefined, api.convertKeyToPath); } else if (api.method === 'post' || api.method === 'put') { api.body = api.data = (0, helper_1.cloneObject)(data); } // get 类请求,把 data 附带到 url 上。 if (api.method === 'get' || api.method === 'jsonp') { if (!~raw.indexOf('$') && !api.data && autoAppend) { api.query = api.data = data; } else if (api.attachDataToQuery === false && api.data && !~raw.indexOf('$') && autoAppend) { var idx_1 = api.url.indexOf('?'); if (~idx_1) { var params = (api.query = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, (0, helper_1.qsparse)(api.url.substring(idx_1 + 1))), data)); api.url = api.url.substring(0, idx_1) + '?' + (0, helper_1.qsstringify)(params); } else { api.query = data; api.url += '?' + (0, helper_1.qsstringify)(data); } } if (api.data && api.attachDataToQuery !== false) { var idx_2 = api.url.indexOf('?'); if (~idx_2) { var params = (api.query = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, (0, helper_1.qsparse)(api.url.substring(idx_2 + 1))), api.data)); api.url = api.url.substring(0, idx_2) + '?' + (0, helper_1.qsstringify)(params); } else { api.query = api.data; api.url += '?' + (0, helper_1.qsstringify)(api.data); } delete api.data; } } if (api.headers) { api.headers = (0, tpl_builtin_1.dataMapping)(api.headers, data); } if (api.requestAdaptor && typeof api.requestAdaptor === 'string') { api.requestAdaptor = str2function(api.requestAdaptor, 'api'); } if (api.adaptor && typeof api.adaptor === 'string') { api.adaptor = str2function(api.adaptor, 'payload', 'response', 'api'); } return api; } exports.buildApi = buildApi; function str2function(contents) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } try { var fn = new (Function.bind.apply(Function, (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([void 0], args, false), [contents], false)))(); return fn; } catch (e) { console.warn(e); return null; } } exports.str2function = str2function; var AsyncFunction = Object.getPrototypeOf(function () { return (0, tslib_1.__awaiter)(this, void 0, void 0, function () { return (0, tslib_1.__generator)(this, function (_a) { return [2 /*return*/]; }); }); }).constructor; function str2AsyncFunction(contents) { var args = []; for (var _i = 1; _i < arguments.length; _i++) { args[_i - 1] = arguments[_i]; } try { var fn = new (AsyncFunction.bind.apply(AsyncFunction, (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([void 0], args, false), [contents], false)))(); return fn; } catch (e) { console.warn(e); return null; } } exports.str2AsyncFunction = str2AsyncFunction; function responseAdaptor(ret, api) { var _a, _b, _c; var data = ret.data; var hasStatusField = true; if (!data) { throw new Error('Response is empty'); } // 返回内容是 string,说明 content-type 不是 json,这时可能是返回了纯文本或 html if (typeof data === 'string') { // 如果是文本类型就尝试解析一下 if (ret.headers && (ret.headers['content-type'] || '').startsWith('text/')) { try { data = JSON.parse(data); if (typeof data === 'undefined') { throw new Error('Response should be JSON'); } } catch (e) { var responseBrief = typeof data === 'string' ? (0, tpl_builtin_1.escapeHtml)(data.substring(0, 100)) : ''; throw new Error("Response should be JSON\n " + responseBrief); } } else { if (api.responseType === 'blob') { throw new Error('Should have "Content-Disposition" in Header'); } else { throw new Error("Content type is wrong \"" + ret.headers['content-type'] + "\""); } } } // 兼容几种常见写法 if (data.hasOwnProperty('errorCode')) { // 阿里 Java 规范 data.status = data.errorCode; data.msg = data.errorMessage; } else if (data.hasOwnProperty('errno')) { data.status = data.errno; data.msg = data.errmsg || data.errstr || data.msg; } else if (data.hasOwnProperty('no')) { data.status = data.no; data.msg = data.error || data.msg; } else if (data.hasOwnProperty('error')) { // Google JSON guide // https://google.github.io/styleguide/jsoncstyleguide.xml#error if (typeof data.error === 'object' && data.error.hasOwnProperty('code')) { data.status = data.error.code; data.msg = data.error.message; } else { data.status = data.error; data.msg = data.errmsg || data.msg; } } if (!data.hasOwnProperty('status')) { hasStatusField = false; } var payload = { // Jay 20001,20002,...是菜鸟打印的接口的status // chencicsy 10003 是action二次确认的status ok: hasStatusField === false || data.status == 0 || [20001, 20002, 20003, 10003].includes(data.status), status: hasStatusField === false ? 0 : data.status, msg: data.msg || data.message, msgTimeout: data.msgTimeout, data: !data.data && !hasStatusField ? data : data.data, /** * @author:chencicsy * @description: 获取文件流形式下载的头部信息 @param {{ headers: any }} */ headers: ret.headers, reqUrl: (_a = ret === null || ret === void 0 ? void 0 : ret.config) === null || _a === void 0 ? void 0 : _a.baseURL }; // 兼容返回 schema 的情况,用于 app 模式 if (data && data.type) { payload.data = data; } if (payload.status == 422) { payload.errors = data.errors; } (0, debug_1.debug)('api', 'response', payload); if (payload.ok && api.responseData) { (0, debug_1.debug)('api', 'before dataMapping', payload.data); var responseData = (0, tpl_builtin_1.dataMapping)(api.responseData, (0, helper_1.createObject)({ api: api }, (Array.isArray(payload.data) ? { items: payload.data } : payload.data) || {})); (0, debug_1.debug)('api', 'after dataMapping', responseData); payload.data = responseData; } if ([20001, 20002, 20003, 10003].includes(data.status)) { payload.data.status = data.status; payload.msg = ''; } if ([10004].includes(data.status)) { if (!(payload === null || payload === void 0 ? void 0 : payload.data)) { payload.data = {}; } payload.data.status = data.status; payload.msg = ((_b = data === null || data === void 0 ? void 0 : data.data) === null || _b === void 0 ? void 0 : _b.showText) ? (_c = data === null || data === void 0 ? void 0 : data.data) === null || _c === void 0 ? void 0 : _c.showText : data === null || data === void 0 ? void 0 : data.msg; } // [20001, 20002, 10003].includes(data.status) && (payload.data.status = data.status) // 20001,20002,...是菜鸟打印的接口的status return payload; } exports.responseAdaptor = responseAdaptor; function wrapFetcher(fn, tracker) { return function (api, data, options) { var _a, _b; api = buildApi(api, data, options); if (api.requestAdaptor) { (0, debug_1.debug)('api', 'before requestAdaptor', api); api = api.requestAdaptor(api) || api; (0, debug_1.debug)('api', 'after requestAdaptor', api); } if (api.data && ((0, helper_1.hasFile)(api.data) || api.dataType === 'form-data')) { api.data = api.data instanceof FormData ? api.data : (0, helper_1.object2formData)(api.data, api.qsOptions); } else if (api.data && typeof api.data !== 'string' && api.dataType === 'form') { api.data = (0, helper_1.qsstringify)(api.data, api.qsOptions); api.headers = api.headers || (api.headers = {}); api.headers['Content-Type'] = 'application/x-www-form-urlencoded'; } else if (api.data && typeof api.data !== 'string' && api.dataType === 'json') { api.data = JSON.stringify(api.data); api.headers = api.headers || (api.headers = {}); api.headers['Content-Type'] = 'application/json'; } (0, debug_1.debug)('api', 'request api', api); tracker === null || tracker === void 0 ? void 0 : tracker({ eventType: 'api', eventData: (0, omit_1.default)(api, ['config', 'data', 'body']) }, api.data); if (((_a = api.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === 'jsonp') { return wrapAdaptor(jsonpFetcher(api), api); } if (typeof api.cache === 'number' && api.cache > 0) { var apiCache = getApiCache(api); return wrapAdaptor(apiCache ? apiCache.cachedPromise : setApiCache(api, fn(api)), api); } // IE 下 get 请求会被缓存,所以自动加个时间戳 if (isIE && api && ((_b = api.method) === null || _b === void 0 ? void 0 : _b.toLocaleLowerCase()) === 'get') { var timeStamp = "_t=" + Date.now(); if (api.url.indexOf('?') === -1) { api.url = api.url + ("?" + timeStamp); } else { api.url = api.url + ("&" + timeStamp); } } return wrapAdaptor(fn(api), api); }; } exports.wrapFetcher = wrapFetcher; function wrapAdaptor(promise, api) { var _this = this; var adaptor = api.adaptor; return adaptor ? promise .then(function (response) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () { var result; return (0, tslib_1.__generator)(this, function (_a) { switch (_a.label) { case 0: (0, debug_1.debug)('api', 'before adaptor data', response.data); result = adaptor(response.data, response, api); if (!(result === null || result === void 0 ? void 0 : result.then)) return [3 /*break*/, 2]; return [4 /*yield*/, result]; case 1: result = _a.sent(); _a.label = 2; case 2: (0, debug_1.debug)('api', 'after adaptor data', result); return [2 /*return*/, (0, tslib_1.__assign)((0, tslib_1.__assign)({}, response), { data: result })]; } }); }); }) .then(function (ret) { return responseAdaptor(ret, api); }) : promise.then(function (ret) { return responseAdaptor(ret, api); }); } exports.wrapAdaptor = wrapAdaptor; function jsonpFetcher(api) { return new Promise(function (resolve, reject) { var _a; var script = document.createElement('script'); var src = api.url; script.async = true; function remove() { if (script) { // @ts-ignore script.onload = script.onreadystatechange = script.onerror = null; if (script.parentNode) { script.parentNode.removeChild(script); } script = null; } } var jsonp = ((_a = api.query) === null || _a === void 0 ? void 0 : _a.callback) || 'axiosJsonpCallback' + (0, helper_1.uuid)(); var old = window[jsonp]; window[jsonp] = function (responseData) { window[jsonp] = old; var response = { data: responseData, status: 200, headers: {} }; resolve(response); }; var additionalParams = { _: new Date().getTime(), _callback: jsonp }; src += (src.indexOf('?') >= 0 ? '&' : '?') + (0, helper_1.qsstringify)(additionalParams); // @ts-ignore IE 为script.onreadystatechange script.onload = script.onreadystatechange = function () { // @ts-ignore if (!script.readyState || /loaded|complete/.test(script.readyState)) { remove(); } }; script.onerror = function () { remove(); var errResponse = { status: 0, headers: {} }; reject(errResponse); }; script.src = src; document.head.appendChild(script); }); } exports.jsonpFetcher = jsonpFetcher; function isApiOutdated(prevApi, nextApi, prevData, nextData) { var _a; if (!nextApi) { return false; } else if (!prevApi) { return true; } nextApi = normalizeApi(nextApi); if (nextApi.autoRefresh === false) { return false; } var trackExpression = (_a = nextApi.trackExpression) !== null && _a !== void 0 ? _a : nextApi.url; if (typeof trackExpression !== 'string' || !~trackExpression.indexOf('$')) { return false; } prevApi = normalizeApi(prevApi); var isModified = false; if (nextApi.trackExpression || prevApi.trackExpression) { isModified = (0, tpl_builtin_1.tokenize)(prevApi.trackExpression || '', prevData) !== (0, tpl_builtin_1.tokenize)(nextApi.trackExpression || '', nextData); } else { prevApi = buildApi(prevApi, prevData, { ignoreData: true }); nextApi = buildApi(nextApi, nextData, { ignoreData: true }); isModified = prevApi.url !== nextApi.url; } return !!(isModified && isValidApi(nextApi.url) && (!nextApi.sendOn || (0, tpl_1.evalExpression)(nextApi.sendOn, nextData))); } exports.isApiOutdated = isApiOutdated; function isValidApi(api) { return (api && /^(?:(https?|wss?|taf):\/\/[^\/]+)?(\/?[^\s\/\?]*){1,}(\?.*)?$/.test(api)); } exports.isValidApi = isValidApi; function isEffectiveApi(api, data, initFetch, initFetchOn) { if (!api) { return false; } if (initFetch === false) { return false; } if (initFetchOn && data && !(0, tpl_1.evalExpression)(initFetchOn, data)) { return false; } if (typeof api === 'string' && api.length) { return true; } else if ((0, helper_1.isObject)(api) && api.url) { if (api.sendOn && data && !(0, tpl_1.evalExpression)(api.sendOn, data)) { return false; } return true; } return false; } exports.isEffectiveApi = isEffectiveApi; function isSameApi(apiA, apiB) { return (apiA.method === apiB.method && apiA.url === apiB.url && !(0, helper_1.isObjectShallowModified)(apiA.data, apiB.data, false)); } exports.isSameApi = isSameApi; function getApiCache(api) { // 清理过期cache var now = Date.now(); var result; for (var idx = 0, len = apiCaches.length; idx < len; idx++) { var apiCache = apiCaches[idx]; if (now - apiCache.requestTime > apiCache.cache) { apiCaches.splice(idx, 1); len--; idx--; continue; } if (isSameApi(api, apiCache)) { result = apiCache; break; } } return result; } exports.getApiCache = getApiCache; function setApiCache(api, promise) { apiCaches.push((0, tslib_1.__assign)((0, tslib_1.__assign)({}, api), { cachedPromise: promise, requestTime: Date.now() })); return promise; } exports.setApiCache = setApiCache; function clearApiCache() { apiCaches.splice(0, apiCaches.length); } exports.clearApiCache = clearApiCache; function normalizeApiResponseData(data) { var _a; if (typeof data === 'undefined') { data = {}; } else if (!(0, isPlainObject_1.default)(data)) { data = (_a = {}, _a[Array.isArray(data) ? 'items' : 'result'] = data, _a); } return data; } exports.normalizeApiResponseData = normalizeApiResponseData; // window.apiCaches = apiCaches; //# sourceMappingURL=./utils/api.js.map