@w6s/codash
Version:
A Cordova utility library.
537 lines (464 loc) • 16.7 kB
JavaScript
/*!
* @w6s/codash.js v1.1.2
* (c) 2020 WorkPlusFE
* Released under the MIT License.
* https://github.com/WorkPlusFE/codash#readme
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('invariant'), require('deepmerge')) :
typeof define === 'function' && define.amd ? define(['exports', 'invariant', 'deepmerge'], factory) :
(factory((global.workplusCodash = {}),global.invariant,global.deepmerge));
}(this, (function (exports,invariant,deepmerge) { 'use strict';
invariant = invariant && invariant.hasOwnProperty('default') ? invariant['default'] : invariant;
deepmerge = deepmerge && deepmerge.hasOwnProperty('default') ? deepmerge['default'] : deepmerge;
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = 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);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var toString = function toString(val) {
return Object.prototype.toString.call(val);
};
var isArray = function isArray(val) {
return toString(val) === '[object Array]';
};
var isFunction = function isFunction(val) {
return toString(val) === '[object Function]';
};
var isString = function isString(val) {
return toString(val) === '[object String]';
};
var isObject = function isObject(val) {
return toString(val) === '[object Object]';
};
var isEmptyObject = function isEmptyObject(obj) {
return isObject(obj) && Object.keys(obj).length === 0;
};
var hasCordova = function hasCordova() {
return typeof cordova !== 'undefined';
};
var getFileName = function getFileName(fileURL) {
return fileURL.substr(fileURL.lastIndexOf('/') + 1);
};
var each = function each(obj, fn) {
if (obj === null || typeof obj === 'undefined') {
return;
}
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) !== 'object') {
obj = [obj];
}
if (isArray(obj)) {
for (var i = 0, l = obj.length; i < l; i += 1) {
fn.call(null, obj[i], i, obj);
}
} else {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
fn.call(null, obj[key], key, obj);
}
}
}
};
var stringToJson = function stringToJson(string) {
try {
return JSON.parse(string);
} catch (e) {
return string;
}
};
var throwMsgWhenCordovaIsUndefined = function throwMsgWhenCordovaIsUndefined() {
invariant(null, 'Make sure that cordova.js is properly introduced and that the <script type="text/javascript" src="applocal://www/cordova.min.js"></script> tag is added to the html page. And make sure to perform the cordova event after deviceReady.');
};
// mockData:
// {
// 'hook': {
// 'action': function(params) {
// return { mock: true };
// }
// }
// }
function cordovaExecMock(config) {
var mockData = config.mockData;
invariant(!isEmptyObject(mockData), '[codash]: mockData can not be empty');
var getMockDataByParams = function getMockDataByParams(hook, action, params) {
var mockHook = mockData[hook];
invariant(mockHook, '[codash]: \'' + hook + '\' not found. Please check the mock data.');
if (mockHook) {
var mockAction = mockData[hook][action];
invariant(mockAction, '[codash]: \'' + action + '\' not found. Please check the mock data.');
if (mockAction) {
if (mockAction === null) return false;
var isFn = isFunction(mockAction);
invariant(isFn, '[codash]: \'' + hook + ' > ' + action + '\' must be a function.');
if (isFn) {
return mockAction;
}
}
}
return false;
};
return function (success, error, hook, action, params) {
var mockAction = getMockDataByParams(hook, action, params);
if (mockAction !== false) {
success(mockAction(params));
} else {
error();
}
};
}
var createResponseData = function createResponseData(config, cordova) {
return function (data) {
var status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var json = config.json;
return {
data: json ? stringToJson(data) : data,
config: config,
cordova: cordova,
status: status,
timeout: timeout
};
};
};
function dispatchCordovaEvent(config) {
var responseFn = void 0;
var mock = config.mock;
if (!hasCordova() && !mock) {
throwMsgWhenCordovaIsUndefined();
responseFn = createResponseData(config, null);
return Promise.resolve(responseFn(null, -1));
}
var _cordova = hasCordova() ? cordova : {};
responseFn = createResponseData(config, _cordova);
return new Promise(function (resolve, reject) {
var hook = config.hook,
action = config.action,
params = config.params;
var timeout = config.timeout,
cache = config.cache;
var execFn = mock ? cordovaExecMock(config) : cordova.exec;
var done = false;
execFn(function (data) {
if (!done) {
done = true;
resolve(responseFn(data));
}
}, function (error) {
done = true;
resolve(responseFn(error, -1));
}, hook, action, params || []);
if (timeout > 0) {
setTimeout(function () {
if (!done) {
done = true;
resolve(responseFn(null, -1, true));
}
}, timeout);
}
});
}
var Interceptor = function () {
function Interceptor() {
classCallCheck(this, Interceptor);
this.handlers = [];
}
/**
* Add a new interceptor to the stack
*
* @param {Function} fulfilled The function to handle `then` for a `Promise`
* @param {Function} rejected The function to handle `reject` for a `Promise`
*
* @return {Number} An ID used to remove interceptor later
*/
createClass(Interceptor, [{
key: 'use',
value: function use(fulfilled, rejected) {
this.handlers.push({
fulfilled: fulfilled,
rejected: rejected
});
return this.handlers.length - 1;
}
/**
* Remove an interceptor from the stack
*
* @param {Number} id The ID that was returned by `use`
*/
}, {
key: 'eject',
value: function eject(id) {
if (this.handlers[id]) {
this.handlers[id] = null;
}
}
/**
* Iterate over all the registered interceptors
*
* This method is particularly useful for skipping over any
* interceptors that may have become `null` calling `eject`.
*
* @param {Function} fn The function to call for each interceptor
*/
}, {
key: 'forEach',
value: function forEach(fn) {
each(this.handlers, function (h) {
if (h !== null) {
fn(h);
}
});
}
}]);
return Interceptor;
}();
var defaultConfig = {
timeout: -1,
json: true,
mock: false,
mockData: {}
};
var Cordova = function () {
function Cordova() {
var instanceConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
classCallCheck(this, Cordova);
this.defaultsConfig = deepmerge(defaultConfig, instanceConfig);
this.interceptors = {
before: new Interceptor(),
after: new Interceptor()
};
}
createClass(Cordova, [{
key: 'handle',
value: function handle(config) {
var dispatchConfig = deepmerge(this.defaultsConfig, config);
var chain = [dispatchCordovaEvent, undefined];
var promise = Promise.resolve(dispatchConfig);
this.interceptors.before.forEach(function (interceptor) {
chain.unshift(interceptor.fulfilled, interceptor.rejected);
});
this.interceptors.after.forEach(function (interceptor) {
chain.push(interceptor.fulfilled, interceptor.rejected);
});
while (chain.length) {
promise = promise.then(chain.shift(), chain.shift());
}
return promise;
}
}, {
key: 'create',
value: function create(hook, action) {
var _this = this;
var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var extend = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
invariant(hook, 'Hook cannot be empty');
invariant(action, 'Action cannot be empty');
var options = deepmerge({ hook: hook, action: action, params: params }, extend);
return function () {
return _this.handle(options);
};
}
}, {
key: 'addHook',
value: function addHook(hook) {
invariant(hook, 'Hook cannot be empty');
invariant(isString(hook), 'Hook must be a string');
var self = this;
return {
create: function create(action) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var extend = arguments[2];
return self.create(hook, action, params, extend);
}
};
}
}, {
key: 'version',
get: function get$$1() {
return cordova ? cordova.version : -1;
}
}]);
return Cordova;
}();
function deviceReady() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _options$timeout = options.timeout,
timeout = _options$timeout === undefined ? 5000 : _options$timeout,
_options$isMock = options.isMock,
isMock = _options$isMock === undefined ? false : _options$isMock,
_options$mock = options.mock,
mock = _options$mock === undefined ? false : _options$mock;
return new Promise(function (resolve, reject) {
if (isMock || mock) {
if (isMock) {
console.warn('isMock 属性将在下个版本弃用,请使用 mock 属性进行设置');
}
console.log('[codash]: Mock device ready.');
return resolve();
}
var ready = false;
setTimeout(function () {
if (!ready) reject({ status: -1, deviceready: false });
}, timeout);
document.addEventListener('deviceready', function () {
ready = true;
resolve();
}, false);
});
}
function bindBackEvent(backEvent) {
var backButtonEvent = function backButtonEvent(channel) {
if (channel.action === 'backbutton') {
backEvent && backEvent();
}
};
cordova.exec(null, null, "CoreAndroid", "overrideBackbutton", [true]);
cordova.exec(backButtonEvent, null, "CoreAndroid", "messageChannel", []);
}
var FileDownload = function () {
function FileDownload() {
classCallCheck(this, FileDownload);
this.fileTransfer = new FileTransfer();
}
createClass(FileDownload, [{
key: 'download',
value: function download(source, target) {
var _this = this;
var trustAllHosts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var options = arguments[3];
return new Promise(function (resolve, reject) {
var successCallback = function successCallback(entry) {
return resolve(entry);
};
var errorCallback = function errorCallback(error) {
return reject(error);
};
_this.fileTransfer.download(encodeURI(source), target, successCallback, errorCallback, trustAllHosts, options);
});
}
}]);
return FileDownload;
}();
/**
* Creates an instance of FileUpload.
*
* @param {object} options
* @memberof FileUpload
*
* {fileKey}: The name of the form element. Defaults to file. (DOMString)
* {fileName}: The file name to use when saving the file on the server. Defaults to image.jpg. (DOMString)
* {httpMethod}: The HTTP method to use - either PUT or POST. Defaults to POST. (DOMString)
* {mimeType}: The mime type of the data to upload. Defaults to image/jpeg. (DOMString)
* {params}: A set of optional key/value pairs to pass in the HTTP request. (Object, key/value - DOMString)
* {chunkedMode}: Whether to upload the data in chunked streaming mode. Defaults to true. (Boolean)
* {headers}: A map of header name/header values. Use a hash to specify one or more than one value. On iOS, FireOS, and Android, if a header named Content-Type is present, multipart form data will NOT be used. (Object)
*
* https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file-transfer/
*/
var FileUpload = function () {
function FileUpload(options) {
classCallCheck(this, FileUpload);
this.fileTransferInstance = new FileTransfer();
this.options = this.initFileUploadOptions(options);
}
createClass(FileUpload, [{
key: 'initFileUploadOptions',
value: function initFileUploadOptions(options) {
var opts = new FileUploadOptions();
for (var key in options) {
opts[key] = options[key];
}
return opts;
}
}, {
key: 'upload',
value: function upload(fileURL, server, options) {
var _this = this;
return new Promise(function (resolve, reject) {
var success = function success(res) {
if (res.responseCode === 200) {
if (options.success && isFunction(options.success)) options.success(res);
return resolve(res);
}
return reject(res);
};
var failure = function failure(err) {
if (options.error && isFunction(options.error)) {
options.error(err);
}
reject(err);
};
_this.fileTransferInstance.onprogress = function (progressEvent) {
var loaded = progressEvent.loaded,
total = progressEvent.total;
if (options.progress && isFunction(options.progress)) {
options.progress(loaded, total);
}
};
_this.fileTransferInstance.upload(fileURL, encodeURI(server), success, failure, _this.options, trustAllHosts = !!options.trustAllHosts);
});
}
}, {
key: 'abort',
value: function abort() {
this.fileTransferInstance.abort();
}
}]);
return FileUpload;
}();
function toBase64(path, success, error) {
function resolveImgURI(fileUrl, callback) {
if (cordova.platformId.toLowerCase() === 'android') {
fileUrl = 'file://' + fileUrl;
}
window.resolveLocalFileSystemURL(fileUrl, function (fileEntry) {
fileEntry.file(function (file) {
readDataUrl(file, callback);
}, fail);
}, fail);
}
function readDataUrl(file, callback) {
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target._result) {
evt.target._result = evt.target._result.split(',')[1];
}
callback(evt);
};
reader.readAsDataURL(file);
}
function fail(evt) {
error(evt);
}
resolveImgURI(path, success);
}
exports.Cordova = Cordova;
exports.deviceReady = deviceReady;
exports.bindBackEvent = bindBackEvent;
exports.FileDownload = FileDownload;
exports.FileUpload = FileUpload;
exports.toBase64 = toBase64;
exports.stringToJson = stringToJson;
exports.getFileName = getFileName;
Object.defineProperty(exports, '__esModule', { value: true });
})));