UNPKG

vue-deepset

Version:
286 lines (248 loc) 8.55 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); 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; }; exports.vueSet = vueSet; exports.vuexSet = vuexSet; exports.VUEX_DEEP_SET = VUEX_DEEP_SET; exports.extendMutation = extendMutation; exports.vueModel = vueModel; exports.vuexModel = vuexModel; exports.deepModel = deepModel; exports.install = install; var _vue = require('vue'); var _vue2 = _interopRequireDefault(_vue); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var invalidKey = /^\d|[^a-zA-Z0-9_]/gm; var intKey = /^\d+$/; function isNumberLike(value) { return String(value).match(/^\d+$/); } function toPath(pathString) { if (Array.isArray(pathString)) return pathString; if (typeof pathString === 'number') return [pathString]; pathString = String(pathString); // taken from lodash - https://github.com/lodash/lodash var pathRx = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g; var pathArray = []; pathString.replace(pathRx, function (match, number, quote, string) { pathArray.push(quote ? string : number !== undefined ? Number(number) : match); return pathArray[pathArray.length - 1]; }); return pathArray; } function noop() {} function hasOwnProperty(object, property) { return Object.prototype.hasOwnProperty.call(object, property); } function deepsetError(message) { return new Error('[vue-deepset]: ' + message); } function isObjectLike(object) { return (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && object !== null; } function pathJoin(base, path) { try { var connector = path.match(/^\[/) ? '' : '.'; return '' + (base || '') + (base ? connector : '') + path; } catch (error) { return ''; } } function pushPaths(object, current, paths) { paths.push(current); if (isObjectLike(object)) { getPaths(object, current, paths); } } function forEach(object, iteratee) { var isArray = Array.isArray(object); var keys = isArray ? object : Object.keys(object); keys.forEach(function (value, index) { return isArray ? iteratee(value, index) : iteratee(object[value], value); }); } function has(object, path) { var obj = object; var parts = toPath(path); while (parts.length) { var key = parts.shift(); if (!hasOwnProperty(obj, key)) { return false; } else if (!parts.length) { return true; } obj = obj[key]; } return false; } function getPaths(object) { var current = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var paths = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; if (Array.isArray(object)) { forEach(object, function (val, idx) { pushPaths(val, (current + '.' + idx).replace(/^\./, ''), paths); pushPaths(val, (current + '[' + idx + ']').replace(/^\./, ''), paths); pushPaths(val, (current + '["' + idx + '"]').replace(/^\./, ''), paths); }); } else if (isObjectLike(object)) { forEach(object, function (val, key) { if (key.match(intKey) !== null) { // is index pushPaths(val, (current + '.' + key).replace(/^\./, ''), paths); pushPaths(val, (current + '[' + key + ']').replace(/^\./, ''), paths); pushPaths(val, (current + '["' + key + '"]').replace(/^\./, ''), paths); } else if (!key.match(invalidKey)) { pushPaths(val, (current + '.' + key).replace(/^\./, ''), paths); } // always add the absolute array notation path pushPaths(val, (current + '["' + key + '"]').replace(/^\./, ''), paths); }); } return [].concat(new Set(paths)); } function _get(obj, path, defaultValue) { try { var o = obj; var fields = toPath(path); while (fields.length) { var prop = fields.shift(); o = o[prop]; if (!fields.length) { return o; } } } catch (err) { return defaultValue; } return defaultValue; } function getProxy(vm, base, options) { noop(options); // for future potential options var isVuex = typeof base === 'string'; var object = isVuex ? _get(vm.$store.state, base) : base; return new Proxy(object, { get: function get(target, property) { return _get(target, property); }, set: function set(target, property, value) { isVuex ? vuexSet.call(vm, pathJoin(base, property), value) : vueSet(target, property, value); return true; }, deleteProperty: function deleteProperty() { return true; }, enumerate: function enumerate(target) { return Object.keys(target); }, ownKeys: function ownKeys(target) { return Object.keys(target); }, has: function has(target, property) { return true; }, defineProperty: function defineProperty(target) { return target; }, getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, property) { return { value: _get(target, property), writable: false, enumerable: true, configurable: true }; } }); } function buildVueModel(vm, object, options) { var model = {}; forEach(getPaths(object), function (path) { Object.defineProperty(model, path, { configurable: true, enumerable: true, get: function get() { return _get(object, path); }, set: function set(value) { return vueSet(object, path, value); } }); }); return model; } function buildVuexModel(vm, vuexPath, options) { var model = Object.create(null); var object = _get(vm.$store.state, vuexPath); var paths = getPaths(object); forEach(paths, function (path) { var propPath = pathJoin(vuexPath, path); Object.defineProperty(model, path, { configurable: true, enumerable: true, get: function get() { return _get(vm.$store.state, propPath); }, set: function set(value) { return vuexSet.call(vm, propPath, value); } }); }); return model; } function vueSet(obj, path, value) { var fields = Array.isArray(path) ? path : toPath(path); var prop = fields.shift(); if (!fields.length) return _vue2.default.set(obj, prop, value); if (!hasOwnProperty(obj, prop) || obj[prop] === null) { var objVal = fields.length >= 1 && isNumberLike(fields[0]) ? [] : {}; _vue2.default.set(obj, prop, objVal); } vueSet(obj[prop], fields, value); } function vuexSet(path, value) { if (!isObjectLike(this.$store)) { throw deepsetError('could not find vuex store object on instance'); } var method = this.$store.commit ? 'commit' : 'dispatch'; this.$store[method]('VUEX_DEEP_SET', { path: path, value: value }); } function VUEX_DEEP_SET(state, _ref) { var path = _ref.path, value = _ref.value; vueSet(state, path, value); } function extendMutation() { var mutations = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return Object.assign(mutations, { VUEX_DEEP_SET: VUEX_DEEP_SET }); } function vueModel(object, options) { var opts = Object.assign({}, options); if (!isObjectLike(object)) { throw deepsetError('invalid object specified for vue model'); } else if (opts.useProxy === false || typeof Proxy === 'undefined') { return buildVueModel(this, object, opts); } return getProxy(this, object, opts); } function vuexModel(vuexPath, options) { var opts = Object.assign({}, options); if (typeof vuexPath !== 'string' || vuexPath === '') { throw deepsetError('invalid vuex path string'); } else if (!isObjectLike(this.$store) || !isObjectLike(this.$store.state)) { throw deepsetError('no vuex state found'); } else if (!has(this.$store.state, vuexPath)) { throw deepsetError('cannot find path "' + vuexPath + '" in Vuex store'); } else if (opts.useProxy === false || typeof Proxy === 'undefined') { return buildVuexModel(this, vuexPath, opts); } return getProxy(this, vuexPath, opts); } function deepModel(base, options) { return typeof base === 'string' ? vuexModel.call(this, base, options) : vueModel.call(this, base, options); } function install(VueInstance) { VueInstance.prototype.$deepModel = deepModel; VueInstance.prototype.$vueSet = vueSet; VueInstance.prototype.$vuexSet = vuexSet; }