Comparing version 2.0.0-dev10 to 2.0.0-dev11
@@ -378,3 +378,3 @@ /** | ||
previousData: previousData, | ||
data: this.data, | ||
currentData: this.data, | ||
paths: affectedPaths | ||
@@ -392,9 +392,9 @@ }); | ||
* | ||
* @param {object|array} paths - Paths to listen. | ||
* @return {Cursor} - A special cursor that can be listened. | ||
* @param {object|array} definition - Paths to listen. | ||
* @return {Cursor} - A special cursor that can be listened. | ||
*/ | ||
value: function watch(paths) { | ||
if (!_type2['default'].object(paths) && !_type2['default'].array(paths)) throw Error('Baobab.watch: wrong argument.'); | ||
value: function watch(definition) { | ||
if (!_type2['default'].watcherDefinition(definition)) throw (0, _helpers.makeError)('Baobab.watch: wrong definition.', { definition: definition }); | ||
return new _cursor2['default'](this, null, { watched: paths }); | ||
return new _cursor2['default'](this, null, { watched: definition }); | ||
} | ||
@@ -454,3 +454,3 @@ }, { | ||
Object.defineProperty(Baobab, 'version', { | ||
value: '2.0.0-dev10' | ||
value: '2.0.0-dev11' | ||
}); | ||
@@ -457,0 +457,0 @@ |
@@ -145,3 +145,3 @@ /** | ||
return _this.emit('update', { | ||
data: _this._get().data, | ||
currentData: _this._get().data, | ||
previousData: record | ||
@@ -821,4 +821,4 @@ }); | ||
makeSetter('unshift'); | ||
makeSetter('splice', _type2['default'].array); | ||
makeSetter('splice', _type2['default'].splicer); | ||
makeSetter('merge', _type2['default'].object); | ||
module.exports = exports['default']; |
@@ -127,3 +127,3 @@ /** | ||
var facetPath = _type2['default'].facetPath(path); | ||
if (!facetPath) return accumulatedPaths.concat(path); | ||
if (!facetPath) return accumulatedPaths.concat([path]); | ||
@@ -130,0 +130,0 @@ // Solving recursive path |
@@ -250,2 +250,14 @@ /** | ||
/** | ||
* Function to partially freeze an object by carefully avoiding the `$` | ||
* keys indicating the presence of facets. | ||
* | ||
* @param {object} o - The object to partially freeze. | ||
*/ | ||
function partialFreeze(o) { | ||
var k = undefined; | ||
for (k in o) if (k[0] !== '$') Object.defineProperty(o, k, { writable: false }); | ||
} | ||
/** | ||
* Function freezing the given variable if possible. | ||
@@ -260,7 +272,12 @@ * | ||
Object.freeze(o); | ||
var isArray = Array.isArray(o), | ||
anyFacet = !isArray && Object.keys(o).some(function (k) { | ||
return k[0] === '$'; | ||
}); | ||
if (anyFacet) partialFreeze(o);else Object.freeze(o); | ||
if (!deep) return; | ||
if (Array.isArray(o)) { | ||
if (isArray) { | ||
@@ -307,3 +324,2 @@ // Iterating through the elements | ||
* @param {object} [parent] - Parent object in the iteration. | ||
* @param {string} [lastKey] - Current value's key in parent. | ||
*/ | ||
@@ -317,9 +333,4 @@ function solveMask(immutable, data, mask, parent) { | ||
if (immutable) deepFreeze(parent); | ||
if (immutable) deepFreeze(data[k]); | ||
} else { | ||
if (immutable) { | ||
data[k] = shallowClone(data[k]); | ||
if (parent) freeze(parent); | ||
} | ||
solveMask(immutable, data[k], mask[k], data); | ||
@@ -326,0 +337,0 @@ } |
@@ -107,2 +107,15 @@ /** | ||
/** | ||
* Checking whether the given variable is a valid splicer. | ||
* | ||
* @param {mixed} target - Variable to test. | ||
* @param {array} [allowed] - Optional valid types in path. | ||
* @return {boolean} | ||
*/ | ||
type.splicer = function (target) { | ||
if (!type.array(target) || target.length < 2) return false; | ||
return anyOf(target[0], ['number', 'function', 'object']) && type.number(target[1]); | ||
}; | ||
/** | ||
* Checking whether the given variable is a valid cursor path. | ||
@@ -114,10 +127,11 @@ * | ||
*/ | ||
type.path = function (target, allowed) { | ||
// Order is important for performance reasons | ||
var ALLOWED_FOR_PATH = ['string', 'number', 'function', 'object']; | ||
type.path = function (target) { | ||
if (!target && target !== 0) return false; | ||
// Order of allowed types is important for perf reasons | ||
allowed = allowed || ['string', 'number', 'function', 'object']; | ||
return [].concat(target).every(function (step) { | ||
return anyOf(step, allowed); | ||
return anyOf(step, ALLOWED_FOR_PATH); | ||
}); | ||
@@ -190,2 +204,17 @@ }; | ||
/** | ||
* Checking whether the given watcher definition is valid. | ||
* | ||
* @param {mixed} definition - The definition to check. | ||
* @return {boolean} | ||
*/ | ||
type.watcherDefinition = function (definition) { | ||
if (type.object(definition)) return Object.keys(definition).every(function (k) { | ||
return type.path(definition[k]); | ||
});else if (type.array(definition)) return definition.every(type.path); | ||
return false; | ||
}; | ||
/** | ||
* Checking whether the given string is a valid operation type. | ||
@@ -192,0 +221,0 @@ * |
@@ -145,3 +145,3 @@ /** | ||
// Else, we shift the reference and continue the path | ||
else { | ||
else if (opts.persistent) { | ||
p[s] = (0, _helpers.shallowClone)(p[s]); | ||
@@ -148,0 +148,0 @@ } |
{ | ||
"name": "baobab", | ||
"version": "2.0.0-dev10", | ||
"version": "2.0.0-dev11", | ||
"description": "JavaScript persistent data tree with cursors.", | ||
@@ -5,0 +5,0 @@ "main": "./dist/baobab.js", |
@@ -140,3 +140,3 @@ [![Build Status](https://travis-ci.org/Yomguithereal/baobab.svg)](https://travis-ci.org/Yomguithereal/baobab) | ||
If you really need to fire an update synchronously (typically if you store a form's state within your app's state, for instance), your remain free to use the `tree.commit` method or tweak the tree's [options](#options) to fit your needs. | ||
If you really need to fire an update synchronously (typically if you store a form's state within your app's state, for instance), your remain free to use the `tree.commit()` method or tweak the tree's [options](#options) to fit your needs. | ||
@@ -361,3 +361,3 @@ **Important**: Note that the tree, being a persistent data structure, will shift the references of the objects it stores in order to enable *immutabley* comparisons between one version of the state and another (this is especially useful when using strategies as such as React's [pure rendering](https://facebook.github.io/react/docs/pure-render-mixin.html)). | ||
console.log('New data:', eventData.data); | ||
console.log('Current data:', eventData.currentData); | ||
console.log('Previous data:', eventData.previousData); | ||
@@ -419,3 +419,6 @@ console.log('Transaction details:', eventData.transaction); | ||
```js | ||
cursor.on('update', fn); | ||
cursor.on('update', function(e) { | ||
console.log('Current data:', eventData.currentData); | ||
console.log('Previous data:', eventData.previousData); | ||
}); | ||
``` | ||
@@ -772,3 +775,3 @@ | ||
```js | ||
// Asynchronous tree so that examples are simpler | ||
// Synchronous tree so that examples are simpler | ||
var baobab = new Baobab({colors: ['blue']}, {asynchronous: false}), | ||
@@ -775,0 +778,0 @@ cursor = baobab.select('colors'); |
@@ -375,3 +375,3 @@ /** | ||
previousData, | ||
data: this.data, | ||
currentData: this.data, | ||
paths: affectedPaths | ||
@@ -387,10 +387,10 @@ }); | ||
* | ||
* @param {object|array} paths - Paths to listen. | ||
* @return {Cursor} - A special cursor that can be listened. | ||
* @param {object|array} definition - Paths to listen. | ||
* @return {Cursor} - A special cursor that can be listened. | ||
*/ | ||
watch(paths) { | ||
if (!type.object(paths) && !type.array(paths)) | ||
throw Error('Baobab.watch: wrong argument.'); | ||
watch(definition) { | ||
if (!type.watcherDefinition(definition)) | ||
throw makeError('Baobab.watch: wrong definition.', {definition}); | ||
return new Cursor(this, null, {watched: paths}); | ||
return new Cursor(this, null, {watched: definition}); | ||
} | ||
@@ -440,3 +440,3 @@ | ||
Object.defineProperty(Baobab, 'version', { | ||
value: '2.0.0-dev10' | ||
value: '2.0.0-dev11' | ||
}); | ||
@@ -443,0 +443,0 @@ |
@@ -136,3 +136,3 @@ /** | ||
return this.emit('update', { | ||
data: this._get().data, | ||
currentData: this._get().data, | ||
previousData: record | ||
@@ -803,3 +803,3 @@ }); | ||
makeSetter('unshift'); | ||
makeSetter('splice', type.array); | ||
makeSetter('splice', type.splicer); | ||
makeSetter('merge', type.object); |
@@ -115,3 +115,3 @@ /** | ||
if (!facetPath) | ||
return accumulatedPaths.concat(path); | ||
return accumulatedPaths.concat([path]); | ||
@@ -118,0 +118,0 @@ // Solving recursive path |
@@ -218,2 +218,16 @@ /** | ||
/** | ||
* Function to partially freeze an object by carefully avoiding the `$` | ||
* keys indicating the presence of facets. | ||
* | ||
* @param {object} o - The object to partially freeze. | ||
*/ | ||
function partialFreeze(o) { | ||
let k; | ||
for (k in o) | ||
if (k[0] !== '$') | ||
Object.defineProperty(o, k, {writable: false}); | ||
} | ||
/** | ||
* Function freezing the given variable if possible. | ||
@@ -229,8 +243,14 @@ * | ||
Object.freeze(o); | ||
const isArray = Array.isArray(o), | ||
anyFacet = !isArray && Object.keys(o).some(k => k[0] === '$'); | ||
if (anyFacet) | ||
partialFreeze(o); | ||
else | ||
Object.freeze(o); | ||
if (!deep) | ||
return; | ||
if (Array.isArray(o)) { | ||
if (isArray) { | ||
@@ -282,3 +302,2 @@ // Iterating through the elements | ||
* @param {object} [parent] - Parent object in the iteration. | ||
* @param {string} [lastKey] - Current value's key in parent. | ||
*/ | ||
@@ -293,11 +312,5 @@ function solveMask(immutable, data, mask, parent) { | ||
if (immutable) | ||
deepFreeze(parent); | ||
deepFreeze(data[k]); | ||
} | ||
else { | ||
if (immutable) { | ||
data[k] = shallowClone(data[k]); | ||
if (parent) | ||
freeze(parent); | ||
} | ||
solveMask(immutable, data[k], mask[k], data); | ||
@@ -383,3 +396,3 @@ } | ||
if (cm && Object.keys(cm).length) { | ||
let patchedData = solveMask(opts.immutable, {root: c}, {root: cm}); | ||
const patchedData = solveMask(opts.immutable, {root: c}, {root: cm}); | ||
c = patchedData.root; | ||
@@ -386,0 +399,0 @@ } |
@@ -104,2 +104,17 @@ /** | ||
/** | ||
* Checking whether the given variable is a valid splicer. | ||
* | ||
* @param {mixed} target - Variable to test. | ||
* @param {array} [allowed] - Optional valid types in path. | ||
* @return {boolean} | ||
*/ | ||
type.splicer = function(target) { | ||
if (!type.array(target) || target.length < 2) | ||
return false; | ||
return anyOf(target[0], ['number', 'function', 'object']) && | ||
type.number(target[1]); | ||
}; | ||
/** | ||
* Checking whether the given variable is a valid cursor path. | ||
@@ -111,10 +126,11 @@ * | ||
*/ | ||
type.path = function(target, allowed) { | ||
// Order is important for performance reasons | ||
const ALLOWED_FOR_PATH = ['string', 'number', 'function', 'object']; | ||
type.path = function(target) { | ||
if (!target && target !== 0) | ||
return false; | ||
// Order of allowed types is important for perf reasons | ||
allowed = allowed || ['string', 'number', 'function', 'object']; | ||
return [].concat(target).every(step => anyOf(step, allowed)); | ||
return [].concat(target).every(step => anyOf(step, ALLOWED_FOR_PATH)); | ||
}; | ||
@@ -190,2 +206,18 @@ | ||
/** | ||
* Checking whether the given watcher definition is valid. | ||
* | ||
* @param {mixed} definition - The definition to check. | ||
* @return {boolean} | ||
*/ | ||
type.watcherDefinition = function(definition) { | ||
if (type.object(definition)) | ||
return Object.keys(definition).every(k => type.path(definition[k])); | ||
else if (type.array(definition)) | ||
return definition.every(type.path); | ||
return false; | ||
}; | ||
/** | ||
* Checking whether the given string is a valid operation type. | ||
@@ -192,0 +224,0 @@ * |
@@ -185,3 +185,3 @@ /** | ||
// Else, we shift the reference and continue the path | ||
else { | ||
else if (opts.persistent) { | ||
p[s] = shallowClone(p[s]); | ||
@@ -188,0 +188,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
162124
4079
910