Skip to content

Commit

Permalink
modifying proxy object to build a composed object, fixes issue with v…
Browse files Browse the repository at this point in the history
…ue 2.4.0 and greater
  • Loading branch information
bhoriuchi committed Aug 15, 2017
1 parent 186fe34 commit 3ef2762
Show file tree
Hide file tree
Showing 16 changed files with 2,392 additions and 172 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,22 +140,34 @@ Vuex mutation that should be registered when using vuexSet

Adds the `VUEX_DEEP_SET` mutation to an optional hash of mutations and returns an updated hash of mutations

##### vueModel ( obj:Object )
##### vueModel ( obj:Object, [options:Object] )

Creates an abstracted model with a set of flat properties that are generated from inspecting the objects properties so that deeply nested properties can be accessed as first level properties

##### vuexModel ( path:String )
**options**
* `useProxy=true` {`Boolean`} - disable use of Proxy when false

##### vuexModel ( path:String, [options:Object] )

The equivalent of `vueModel` for `vuex`. Path should point to the base object

##### deepModel ( obj:Object )
**options**
* `useProxy=true` {`Boolean`} - disable use of Proxy when false

##### deepModel ( obj:Object, [options:Object] )

Equivalent to `vueModel`

##### deepModel ( path:String )
**options**
* `useProxy=true` {`Boolean`} - disable use of Proxy when false

##### deepModel ( path:String, [options:Object] )

Equivalent to `vuexModel`

**options**
* `useProxy=true` {`Boolean`} - disable use of Proxy when false

### Non-Plugin usage

##### Example - Browser
Expand Down
2 changes: 2 additions & 0 deletions build/liteutils.build.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ var config = {
'reduce',
'toPath',
'isArray',
'isDate',
'isEmpty',
'has',
'isNumber',
'get',
Expand Down
182 changes: 129 additions & 53 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ reduce._dependencies = ['dash.forEach', 'dash.isObject', 'dash.isArray', 'dash.i

/* eslint-disable */
function toPath(pathString) {
if (isArray(pathString)) return pathString;
if (isNumber(pathString)) return [pathString];

// taken from lodash - https://github.com/lodash/lodash
var pathRx = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g;
var pathArray = [];
Expand All @@ -256,13 +259,31 @@ function toPath(pathString) {

toPath._accepts = [String];

/* eslint-disable */
function isDate(obj) {
return obj instanceof Date;
}

isDate._accepts = ['ANY'];

/* eslint-disable */
function isEmpty(obj) {
if (obj === '' || obj === null || obj === undefined) return true;
if ((obj instanceof Buffer || Array.isArray(obj)) && !obj.length) return true;
if ((obj instanceof Map || obj instanceof Set) && !obj.size) return true;
if ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && !Object.keys(obj).length) return true;
return false;
}

isEmpty._accepts = ['ANY'];

/* eslint-disable */
function has(obj, path) {
var found = true;
var fields = isNumber(path) ? [path] : isArray(path) ? path : toPath(path);
var fields = isArray(path) ? path : toPath(path);
if (!fields.length) return false;
forEach(fields, function (field) {
if (obj[field] === undefined) {
if (!obj.hasOwnProperty(field) || obj.hasOwnProperty(field) && obj[field] === undefined) {
found = false;
return false;
}
Expand Down Expand Up @@ -301,6 +322,8 @@ var _ = {
reduce: reduce,
toPath: toPath,
isArray: isArray,
isDate: isDate,
isEmpty: isEmpty,
has: has,
isNumber: isNumber,
get: get$1,
Expand Down Expand Up @@ -357,7 +380,13 @@ function getPaths(obj) {
var k = key.match(INVALID_KEY_RX) ? '["' + key + '"]' : '.' + key;
var cur = ('' + current + k).replace(/^\./, '');
paths.push(cur);
if (isHash(val)) getPaths(val, cur, paths);
if (isHash(val) || _.isArray(val)) getPaths(val, cur, paths);
});
} else if (_.isArray(obj)) {
_.forEach(obj, function (val, idx) {
var cur = current + '[' + idx + ']';
paths.push(cur);
if (isHash(val) || _.isArray(val)) getPaths(val, cur, paths);
});
}
return _.uniq(paths);
Expand Down Expand Up @@ -387,13 +416,9 @@ function vueSet(obj, path, value) {
var fields = _.isArray(path) ? path : _.toPath(path);
var prop = fields.shift();

if (!fields.length) return Vue.nextTick(function () {
return Vue.set(obj, prop, value);
});
if (!fields.length) return Vue.set(obj, prop, value);
if (!_.has(obj, prop)) Vue.set(obj, prop, _.isNumber(prop) ? [] : {});
Vue.nextTick(function () {
return vueSet(obj[prop], fields, value);
});
vueSet(obj[prop], fields, value);
}

/**
Expand Down Expand Up @@ -428,83 +453,134 @@ function extendMutation() {
}

/**
* returns an object that can deep set fields in a vuex store
* builds a new model object based on the values
* @param vuexPath
* @returns {{}}
* @param options
* @returns {Object}
*/
function vuexModel(vuexPath) {
function buildVuexModel(vuexPath, options) {
var _this = this;

var model = {};
var obj = _.get(this.$store.state, vuexPath, this.$store.state);
_.forEach(getPaths(obj), function (path) {
var propPath = pathJoin(vuexPath, path);
Object.defineProperty(model, path, {
configurable: true,
enumerable: true,
get: function get$$1() {
return _.get(_this.$store.state, propPath);
},
set: function set$$1(value) {
vuexSet.call(_this, propPath, value);
}
});
});
return model;
}

/**
* returns an object that can deep set fields in a vuex store
* @param vuexPath
* @returns {Object}
*/
function vuexModel(vuexPath, options) {
var _this2 = this;

if (!_.isString(vuexPath)) throw new Error('VueDeepSet: invalid vuex path string');
options = isHash(options) ? options : {};

if ((typeof Proxy === 'undefined' ? 'undefined' : _typeof(Proxy)) === undefined) {
var model = {};
var obj = _.get(this.$store.state, vuexPath);
_.forEach(getPaths(obj), function (path) {
var propPath = pathJoin(vuexPath, path);
Object.defineProperty(model, path, {
configurable: true,
enumerable: true,
get: function get$$1() {
return _.get(_this.$store.state, propPath);
},
set: function set$$1(value) {
vuexSet.call(_this, propPath, value);
}
});
});
return model;
if (options.useProxy === false || (typeof Proxy === 'undefined' ? 'undefined' : _typeof(Proxy)) === undefined) {
return buildVuexModel.call(this, vuexPath, options);
} else {
return new Proxy(_.get(this.$store.state, vuexPath, this.$store.state), {
var obj = _.get(this.$store.state, vuexPath, this.$store.state);
var tgt = { model: buildVuexModel.call(this, vuexPath, options) };
return new Proxy(obj, {
get: function get$$1(target, property) {
return _.get(_this.$store.state, pathJoin(vuexPath, property));
if (!(property in tgt.model)) {
vuexSet.call(_this2, pathJoin(vuexPath, property), undefined);
tgt.model = buildVuexModel.call(_this2, vuexPath, options);
}
return _.get(_this2.$store.state, pathJoin(vuexPath, property));
},
set: function set$$1(target, property, value) {
vuexSet.call(_this, pathJoin(vuexPath, property), value);
vuexSet.call(_this2, pathJoin(vuexPath, property), value);
return true;
},
has: function has$$1(target, property) {
if (!(property in tgt.model)) {
vuexSet.call(_this2, pathJoin(vuexPath, property), undefined);
tgt.model = buildVuexModel.call(_this2, vuexPath, options);
}
return true;
}
});
}
}

/**
* builds a new model object based on the values
* @param obj
* @param options
* @returns {Object}
*/
function buildVueModel(obj, options) {
var _this3 = this;

var model = {};
_.forEach(getPaths(obj), function (path) {
Object.defineProperty(model, path, {
configurable: true,
enumerable: true,
get: function get$$1() {
return _.get(obj, path);
},
set: function set$$1(value) {
vueSet.call(_this3, obj, path, value);
}
});
});
return model;
}

/**
* returns an object that can deep set fields in a vue.js object
* @param obj
* @returns {Array}
*/
function vueModel(obj) {
var _this2 = this;
function vueModel(obj, options) {
var _this4 = this;

if (!_.isObject(obj)) throw new Error('VueDeepSet: invalid object');
options = isHash(options) ? options : {};

if (typeof Proxy === 'undefined') {
var model = {};
_.forEach(getPaths(obj), function (path) {
Object.defineProperty(model, path, {
configurable: true,
enumerable: true,
get: function get$$1() {
return _.get(obj, path);
},
set: function set$$1(value) {
vueSet.call(_this2, obj, path, value);
}
});
});
return model;
// make _isVue non-enumerable
Object.defineProperty(obj, '_isVue', {
enumerable: false,
writable: true
});

if (options.useProxy === false || typeof Proxy === 'undefined') {
return buildVueModel.call(this, obj, options);
} else {
var tgt = { model: buildVueModel.call(this, obj, options) };
return new Proxy(obj, {
get: function get$$1(target, property) {
return _.get(target, property);
if (!(property in tgt.model)) {
vueSet.call(_this4, obj, property, undefined);
tgt.model = buildVueModel.call(_this4, obj, options);
}
return tgt.model[property];
},
set: function set$$1(target, property, value) {
vueSet.call(_this2, target, property, value);
vueSet.call(_this4, tgt.model, property, value);
return true;
},
has: function has$$1(target, property) {
if (!(property in tgt.model)) {
vueSet.call(_this4, obj, property, undefined);
tgt.model = buildVueModel.call(_this4, obj, options);
}
return true;
}
});
Expand All @@ -516,8 +592,8 @@ function vueModel(obj) {
* @param arg
* @returns {{}}
*/
function deepModel(arg) {
return _.isString(arg) ? vuexModel.call(this, arg) : vueModel.call(this, arg);
function deepModel(arg, options) {
return _.isString(arg) ? vuexModel.call(this, arg, options) : vueModel.call(this, arg, options);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-deepset",
"version": "0.3.1",
"version": "0.4.0",
"description": "Deep set Vue.js objects",
"main": "index.js",
"scripts": {
Expand Down
9 changes: 2 additions & 7 deletions src/liteutils/dash.has.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
/* eslint-disable */
import forEach from './dash.forEach'
import isArray from './dash.isArray'
import isNumber from './dash.isNumber'
import toPath from './dash.toPath'

function has (obj, path) {
let found = true
let fields = isNumber(path)
? [ path ]
: isArray(path)
? path
: toPath(path)
let fields = isArray(path) ? path : toPath(path)
if (!fields.length) return false
forEach(fields, (field) => {
if (obj[field] === undefined) {
if (!obj.hasOwnProperty(field) || (obj.hasOwnProperty(field) && obj[field] === undefined)) {
found = false
return false
}
Expand Down
3 changes: 1 addition & 2 deletions src/liteutils/dash.index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable */
import _dash from './dash'

let DashChain = function (obj) {
Expand All @@ -20,7 +19,7 @@ for (const name in _dash) {
DashChain.prototype[name] = function () {
let args = [this._value].concat([ ...arguments ])
this._value = fn.apply(this, args)
return fn._terminates == true ? this._value : this
return fn._terminates === true ? this._value : this
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/liteutils/dash.isDate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* eslint-disable */
function isDate (obj) {
return obj instanceof Date
}

isDate._accepts = ['ANY']

export default isDate
12 changes: 12 additions & 0 deletions src/liteutils/dash.isEmpty.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable */
function isEmpty (obj) {
if (obj === '' || obj === null || obj === undefined) return true
if ((obj instanceof Buffer || Array.isArray(obj)) && !obj.length) return true
if ((obj instanceof Map || obj instanceof Set) && !obj.size) return true
if (typeof obj === 'object' && !Object.keys(obj).length) return true
return false
}

isEmpty._accepts = ['ANY']

export default isEmpty
Loading

0 comments on commit 3ef2762

Please sign in to comment.