EASYAIuniappNewUI/node_modules/@dcloudio/uni-app-harmony/dist/uni.api.js
2025-02-08 18:50:38 +08:00

616 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { isArray, hasOwn, isString, isPlainObject, isObject, toRawType, capitalize, makeMap, isFunction, isPromise, extend, remove } from '@vue/shared';
function validateProtocolFail(name, msg) {
console.warn(`${name}: ${msg}`);
}
function validateProtocol(name, data, protocol, onFail) {
if (!onFail) {
onFail = validateProtocolFail;
}
for (const key in protocol) {
const errMsg = validateProp(key, data[key], protocol[key], !hasOwn(data, key));
if (isString(errMsg)) {
onFail(name, errMsg);
}
}
}
function validateProtocols(name, args, protocol, onFail) {
if (!protocol) {
return;
}
if (!isArray(protocol)) {
return validateProtocol(name, args[0] || Object.create(null), protocol, onFail);
}
const len = protocol.length;
const argsLen = args.length;
for (let i = 0; i < len; i++) {
const opts = protocol[i];
const data = Object.create(null);
if (argsLen > i) {
data[opts.name] = args[i];
}
validateProtocol(name, data, { [opts.name]: opts }, onFail);
}
}
function validateProp(name, value, prop, isAbsent) {
if (!isPlainObject(prop)) {
prop = { type: prop };
}
const { type, required, validator } = prop;
// required!
if (required && isAbsent) {
return 'Missing required args: "' + name + '"';
}
// missing but optional
if (value == null && !required) {
return;
}
// type check
if (type != null) {
let isValid = false;
const types = isArray(type) ? type : [type];
const expectedTypes = [];
// value is valid as long as one of the specified types match
for (let i = 0; i < types.length && !isValid; i++) {
const { valid, expectedType } = assertType(value, types[i]);
expectedTypes.push(expectedType || '');
isValid = valid;
}
if (!isValid) {
return getInvalidTypeMessage(name, value, expectedTypes);
}
}
// custom validator
if (validator) {
return validator(value);
}
}
const isSimpleType = /*#__PURE__*/ makeMap('String,Number,Boolean,Function,Symbol');
function assertType(value, type) {
let valid;
const expectedType = getType(type);
if (isSimpleType(expectedType)) {
const t = typeof value;
valid = t === expectedType.toLowerCase();
// for primitive wrapper objects
if (!valid && t === 'object') {
valid = value instanceof type;
}
}
else if (expectedType === 'Object') {
valid = isObject(value);
}
else if (expectedType === 'Array') {
valid = isArray(value);
}
else {
if (__PLATFORM__ === 'app') {
// App平台ArrayBuffer等参数跨实例传输无法通过 instanceof 识别
valid = value instanceof type || toRawType(value) === getType(type);
}
else {
valid = value instanceof type;
}
}
return {
valid,
expectedType,
};
}
function getInvalidTypeMessage(name, value, expectedTypes) {
let message = `Invalid args: type check failed for args "${name}".` +
` Expected ${expectedTypes.map(capitalize).join(', ')}`;
const expectedType = expectedTypes[0];
const receivedType = toRawType(value);
const expectedValue = styleValue(value, expectedType);
const receivedValue = styleValue(value, receivedType);
// check if we need to specify expected value
if (expectedTypes.length === 1 &&
isExplicable(expectedType) &&
!isBoolean(expectedType, receivedType)) {
message += ` with value ${expectedValue}`;
}
message += `, got ${receivedType} `;
// check if we need to specify received value
if (isExplicable(receivedType)) {
message += `with value ${receivedValue}.`;
}
return message;
}
function getType(ctor) {
const match = ctor && ctor.toString().match(/^\s*function (\w+)/);
return match ? match[1] : '';
}
function styleValue(value, type) {
if (type === 'String') {
return `"${value}"`;
}
else if (type === 'Number') {
return `${Number(value)}`;
}
else {
return `${value}`;
}
}
function isExplicable(type) {
const explicitTypes = ['string', 'number', 'boolean'];
return explicitTypes.some((elem) => type.toLowerCase() === elem);
}
function isBoolean(...args) {
return args.some((elem) => elem.toLowerCase() === 'boolean');
}
function tryCatch(fn) {
return function () {
try {
return fn.apply(fn, arguments);
}
catch (e) {
// TODO
console.error(e);
}
};
}
let invokeCallbackId = 1;
const invokeCallbacks = {};
function addInvokeCallback(id, name, callback, keepAlive = false) {
invokeCallbacks[id] = {
name,
keepAlive,
callback,
};
return id;
}
// onNativeEventReceive((event,data)=>{}) 需要两个参数,目前写死最多两个参数
function invokeCallback(id, res, extras) {
if (typeof id === 'number') {
const opts = invokeCallbacks[id];
if (opts) {
if (!opts.keepAlive) {
delete invokeCallbacks[id];
}
return opts.callback(res, extras);
}
}
return res;
}
function findInvokeCallbackByName(name) {
for (const key in invokeCallbacks) {
if (invokeCallbacks[key].name === name) {
return true;
}
}
return false;
}
function removeKeepAliveApiCallback(name, callback) {
for (const key in invokeCallbacks) {
const item = invokeCallbacks[key];
if (item.callback === callback && item.name === name) {
delete invokeCallbacks[key];
}
}
}
function offKeepAliveApiCallback(name) {
UniServiceJSBridge.off('api.' + name);
}
function onKeepAliveApiCallback(name) {
UniServiceJSBridge.on('api.' + name, (res) => {
for (const key in invokeCallbacks) {
const opts = invokeCallbacks[key];
if (opts.name === name) {
opts.callback(res);
}
}
});
}
function createKeepAliveApiCallback(name, callback) {
return addInvokeCallback(invokeCallbackId++, name, callback, true);
}
const API_SUCCESS = 'success';
const API_FAIL = 'fail';
const API_COMPLETE = 'complete';
function getApiCallbacks(args) {
const apiCallbacks = {};
for (const name in args) {
const fn = args[name];
if (isFunction(fn)) {
apiCallbacks[name] = tryCatch(fn);
delete args[name];
}
}
return apiCallbacks;
}
function normalizeErrMsg(errMsg, name) {
if (!errMsg || errMsg.indexOf(':fail') === -1) {
return name + ':ok';
}
return name + errMsg.substring(errMsg.indexOf(':fail'));
}
function createAsyncApiCallback(name, args = {}, { beforeAll, beforeSuccess } = {}) {
if (!isPlainObject(args)) {
args = {};
}
const { success, fail, complete } = getApiCallbacks(args);
const hasSuccess = isFunction(success);
const hasFail = isFunction(fail);
const hasComplete = isFunction(complete);
const callbackId = invokeCallbackId++;
addInvokeCallback(callbackId, name, (res) => {
res = res || {};
res.errMsg = normalizeErrMsg(res.errMsg, name);
isFunction(beforeAll) && beforeAll(res);
if (res.errMsg === name + ':ok') {
isFunction(beforeSuccess) && beforeSuccess(res, args);
hasSuccess && success(res);
}
else {
hasFail && fail(res);
}
hasComplete && complete(res);
});
return callbackId;
}
const HOOK_SUCCESS = 'success';
const HOOK_FAIL = 'fail';
const HOOK_COMPLETE = 'complete';
const globalInterceptors = {};
const scopedInterceptors = {};
function wrapperHook(hook, params) {
return function (data) {
return hook(data, params) || data;
};
}
function queue(hooks, data, params) {
let promise = false;
for (let i = 0; i < hooks.length; i++) {
const hook = hooks[i];
if (promise) {
promise = Promise.resolve(wrapperHook(hook, params));
}
else {
const res = hook(data, params);
if (isPromise(res)) {
promise = Promise.resolve(res);
}
if (res === false) {
return {
then() { },
catch() { },
};
}
}
}
return (promise || {
then(callback) {
return callback(data);
},
catch() { },
});
}
function wrapperOptions(interceptors, options = {}) {
[HOOK_SUCCESS, HOOK_FAIL, HOOK_COMPLETE].forEach((name) => {
const hooks = interceptors[name];
if (!isArray(hooks)) {
return;
}
const oldCallback = options[name];
options[name] = function callbackInterceptor(res) {
queue(hooks, res, options).then((res) => {
return (isFunction(oldCallback) && oldCallback(res)) || res;
});
};
});
return options;
}
function wrapperReturnValue(method, returnValue) {
const returnValueHooks = [];
if (isArray(globalInterceptors.returnValue)) {
returnValueHooks.push(...globalInterceptors.returnValue);
}
const interceptor = scopedInterceptors[method];
if (interceptor && isArray(interceptor.returnValue)) {
returnValueHooks.push(...interceptor.returnValue);
}
returnValueHooks.forEach((hook) => {
returnValue = hook(returnValue) || returnValue;
});
return returnValue;
}
function getApiInterceptorHooks(method) {
const interceptor = Object.create(null);
Object.keys(globalInterceptors).forEach((hook) => {
if (hook !== 'returnValue') {
interceptor[hook] = globalInterceptors[hook].slice();
}
});
const scopedInterceptor = scopedInterceptors[method];
if (scopedInterceptor) {
Object.keys(scopedInterceptor).forEach((hook) => {
if (hook !== 'returnValue') {
interceptor[hook] = (interceptor[hook] || []).concat(scopedInterceptor[hook]);
}
});
}
return interceptor;
}
function invokeApi(method, api, options, params) {
const interceptor = getApiInterceptorHooks(method);
if (interceptor && Object.keys(interceptor).length) {
if (isArray(interceptor.invoke)) {
const res = queue(interceptor.invoke, options);
return res.then((options) => {
// 重新访问 getApiInterceptorHooks, 允许 invoke 中再次调用 addInterceptor,removeInterceptor
return api(wrapperOptions(getApiInterceptorHooks(method), options), ...params);
});
}
else {
return api(wrapperOptions(interceptor, options), ...params);
}
}
return api(options, ...params);
}
function hasCallback(args) {
if (isPlainObject(args) &&
[API_SUCCESS, API_FAIL, API_COMPLETE].find((cb) => isFunction(args[cb]))) {
return true;
}
return false;
}
function handlePromise(promise) {
// if (__UNI_FEATURE_PROMISE__) {
// return promise
// .then((data) => {
// return [null, data]
// })
// .catch((err) => [err])
// }
return promise;
}
function promisify(name, fn) {
return (args = {}, ...rest) => {
if (hasCallback(args)) {
return wrapperReturnValue(name, invokeApi(name, fn, args, rest));
}
return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => {
invokeApi(name, fn, extend(args, { success: resolve, fail: reject }), rest);
})));
};
}
function formatApiArgs(args, options) {
const params = args[0];
if (!options ||
!options.formatArgs ||
(!isPlainObject(options.formatArgs) && isPlainObject(params))) {
return;
}
const formatArgs = options.formatArgs;
const keys = Object.keys(formatArgs);
for (let i = 0; i < keys.length; i++) {
const name = keys[i];
const formatterOrDefaultValue = formatArgs[name];
if (isFunction(formatterOrDefaultValue)) {
const errMsg = formatterOrDefaultValue(args[0][name], params);
if (isString(errMsg)) {
return errMsg;
}
}
else {
// defaultValue
if (!hasOwn(params, name)) {
params[name] = formatterOrDefaultValue;
}
}
}
}
function invokeSuccess(id, name, res) {
const result = {
errMsg: name + ':ok',
};
{
result.errSubject = name;
}
return invokeCallback(id, extend((res || {}), result));
}
function invokeFail(id, name, errMsg, errRes = {}) {
const errMsgPrefix = name + ':fail';
let apiErrMsg = '';
if (!errMsg) {
apiErrMsg = errMsgPrefix;
}
else if (errMsg.indexOf(errMsgPrefix) === 0) {
apiErrMsg = errMsg;
}
else {
apiErrMsg = errMsgPrefix + ' ' + errMsg;
}
let res = extend({ errMsg: apiErrMsg }, errRes);
{
if (typeof UniError !== 'undefined') {
res =
typeof errRes.errCode !== 'undefined'
? new UniError(name, errRes.errCode, apiErrMsg)
: new UniError(apiErrMsg, errRes);
}
}
return invokeCallback(id, res);
}
function beforeInvokeApi(name, args, protocol, options) {
if ((process.env.NODE_ENV !== 'production')) {
validateProtocols(name, args, protocol);
}
if (options && options.beforeInvoke) {
const errMsg = options.beforeInvoke(args);
if (isString(errMsg)) {
return errMsg;
}
}
const errMsg = formatApiArgs(args, options);
if (errMsg) {
return errMsg;
}
}
function checkCallback(callback) {
if (!isFunction(callback)) {
throw new Error('Invalid args: type check failed for args "callback". Expected Function');
}
}
function wrapperOnApi(name, fn, options) {
return (callback) => {
checkCallback(callback);
const errMsg = beforeInvokeApi(name, [callback], undefined, options);
if (errMsg) {
throw new Error(errMsg);
}
// 是否是首次调用on,如果是首次需要初始化onMethod监听
const isFirstInvokeOnApi = !findInvokeCallbackByName(name);
createKeepAliveApiCallback(name, callback);
if (isFirstInvokeOnApi) {
onKeepAliveApiCallback(name);
fn();
}
};
}
function wrapperOffApi(name, fn, options) {
return (callback) => {
checkCallback(callback);
const errMsg = beforeInvokeApi(name, [callback], undefined, options);
if (errMsg) {
throw new Error(errMsg);
}
name = name.replace('off', 'on');
removeKeepAliveApiCallback(name, callback);
// 是否还存在监听若已不存在则移除onMethod监听
const hasInvokeOnApi = findInvokeCallbackByName(name);
if (!hasInvokeOnApi) {
offKeepAliveApiCallback(name);
fn();
}
};
}
function parseErrMsg(errMsg) {
if (!errMsg || isString(errMsg)) {
return errMsg;
}
if (errMsg.stack) {
return errMsg.message;
}
return errMsg;
}
function wrapperTaskApi(name, fn, protocol, options) {
return (args) => {
const id = createAsyncApiCallback(name, args, options);
const errMsg = beforeInvokeApi(name, [args], protocol, options);
if (errMsg) {
return invokeFail(id, name, errMsg);
}
return fn(args, {
resolve: (res) => invokeSuccess(id, name, res),
reject: (errMsg, errRes) => invokeFail(id, name, parseErrMsg(errMsg), errRes),
});
};
}
function wrapperSyncApi(name, fn, protocol, options) {
return (...args) => {
const errMsg = beforeInvokeApi(name, args, protocol, options);
if (errMsg) {
throw new Error(errMsg);
}
return fn.apply(null, args);
};
}
function wrapperAsyncApi(name, fn, protocol, options) {
return wrapperTaskApi(name, fn, protocol, options);
}
function defineOnApi(name, fn, options) {
return wrapperOnApi(name, fn, options);
}
function defineOffApi(name, fn, options) {
return wrapperOffApi(name, fn, options);
}
function defineTaskApi(name, fn, protocol, options) {
return promisify(name, wrapperTaskApi(name, fn, (process.env.NODE_ENV !== 'production') ? protocol : undefined, options));
}
function defineSyncApi(name, fn, protocol, options) {
return wrapperSyncApi(name, fn, (process.env.NODE_ENV !== 'production') ? protocol : undefined, options);
}
function defineAsyncApi(name, fn, protocol, options) {
return promisify(name, wrapperAsyncApi(name, fn, (process.env.NODE_ENV !== 'production') ? protocol : undefined, options));
}
const API_ADD_INTERCEPTOR = 'addInterceptor';
const API_REMOVE_INTERCEPTOR = 'removeInterceptor';
const AddInterceptorProtocol = [
{
name: 'method',
type: [String, Object],
required: true,
},
];
const RemoveInterceptorProtocol = AddInterceptorProtocol;
function mergeInterceptorHook(interceptors, interceptor) {
Object.keys(interceptor).forEach((hook) => {
if (isFunction(interceptor[hook])) {
interceptors[hook] = mergeHook(interceptors[hook], interceptor[hook]);
}
});
}
function removeInterceptorHook(interceptors, interceptor) {
if (!interceptors || !interceptor) {
return;
}
Object.keys(interceptor).forEach((name) => {
const hooks = interceptors[name];
const hook = interceptor[name];
if (isArray(hooks) && isFunction(hook)) {
remove(hooks, hook);
}
});
}
function mergeHook(parentVal, childVal) {
const res = childVal
? parentVal
? parentVal.concat(childVal)
: isArray(childVal)
? childVal
: [childVal]
: parentVal;
return res ? dedupeHooks(res) : res;
}
function dedupeHooks(hooks) {
const res = [];
for (let i = 0; i < hooks.length; i++) {
if (res.indexOf(hooks[i]) === -1) {
res.push(hooks[i]);
}
}
return res;
}
const addInterceptor = defineSyncApi(API_ADD_INTERCEPTOR, (method, interceptor) => {
if (isString(method) && isPlainObject(interceptor)) {
mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), interceptor);
}
else if (isPlainObject(method)) {
mergeInterceptorHook(globalInterceptors, method);
}
}, AddInterceptorProtocol);
const removeInterceptor = defineSyncApi(API_REMOVE_INTERCEPTOR, (method, interceptor) => {
if (isString(method)) {
if (isPlainObject(interceptor)) {
removeInterceptorHook(scopedInterceptors[method], interceptor);
}
else {
delete scopedInterceptors[method];
}
}
else if (isPlainObject(method)) {
removeInterceptorHook(globalInterceptors, method);
}
}, RemoveInterceptorProtocol);
export { addInterceptor, defineAsyncApi, defineOffApi, defineOnApi, defineSyncApi, defineTaskApi, removeInterceptor };