Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

baobab

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

baobab - npm Package Compare versions

Comparing version 2.0.0-dev3 to 2.0.0-dev4

3

CHANGELOG.md

@@ -7,3 +7,3 @@ # Changelog

* Cursor's setters method won't return themselves but rather the affected node now.
* Adding `cursor.append` and `cursor.prepend`, replacing some `cursor.push` and `cursor.unshift` weird behaviors.
* Adding `cursor.concat`.
* Adding the `cursor.serialize` method.

@@ -16,2 +16,3 @@ * Adding the `cursor.project` method.

* Update events are now exposing the detail of each transaction so you can replay them elsewhere.
* Fixing `cursor.push/unshift` behavior.
* Dropped the `$cursor` helper.

@@ -18,0 +19,0 @@ * Dropped the `update` specs for a simpler transaction syntax.

@@ -98,2 +98,4 @@ /**

var Baobab = (function (_Emitter) {
_inherits(Baobab, _Emitter);
function Baobab(initialData, opts) {

@@ -140,3 +142,3 @@ var _this = this;

['append', 'apply', 'get', 'prepend', 'push', 'merge', 'project', 'serialize', 'set', 'splice', 'unset', 'unshift'].forEach(bootstrap);
['apply', 'concat', 'get', 'push', 'merge', 'project', 'serialize', 'set', 'splice', 'unset', 'unshift'].forEach(bootstrap);

@@ -147,4 +149,2 @@ // Creating the computed data index for the first time

_inherits(Baobab, _Emitter);
_createClass(Baobab, [{

@@ -158,7 +158,6 @@ key: '_refreshComputedDataIndex',

* @param {array} [path] - Path to the modified node.
* @param {string} [operation] - Type of the applied operation.
* @param {mixed} [node] - The new node.
* @return {Baobab} - The tree itself for chaining purposes.
*/
value: function _refreshComputedDataIndex(path, operation, node) {
value: function _refreshComputedDataIndex(path, node) {
var _this2 = this;

@@ -168,3 +167,3 @@

var walk = function walk(data) {
var p = arguments[1] === undefined ? [] : arguments[1];
var p = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];

@@ -198,2 +197,7 @@ // Have we reached the end?

}
// else {
// // Walk the affected leaf
// return walk(node, path);
// }
}

@@ -285,2 +289,6 @@ }, {

// Refreshing facet index
// TODO: provide a setting to disable this or at least selectively for perf
this._refreshComputedDataIndex(solvedPath, node);
// Updating data and transaction

@@ -295,5 +303,3 @@ this.data = data;

// Should we let the user commit?
if (!this.options.autoCommit) {
return node;
}
if (!this.options.autoCommit) return node;

@@ -438,3 +444,3 @@ // Should we update asynchronously?

Object.defineProperty(Baobab, 'version', {
value: '2.0.0-dev3'
value: '2.0.0-dev4'
});

@@ -441,0 +447,0 @@

@@ -34,2 +34,13 @@ /**

/**
* Traversal helper function for dynamic cursors. Will throw a legible error
* if traversal is not possible.
*
* @param {string} method - The method name, to create a correct error msg.
* @param {array} solvedPath - The cursor's solved path.
*/
function checkPossibilityOfDynamicTraversal(method, solvedPath) {
if (!solvedPath) throw (0, _helpers.makeError)('Baobab.Cursor.' + method + ': ' + ('cannot use ' + method + ' on an unresolved dynamic path.'), { path: solvedPath });
}
/**
* Cursor class

@@ -46,6 +57,8 @@ *

var Cursor = (function (_Emitter) {
_inherits(Cursor, _Emitter);
function Cursor(tree, path) {
var _this = this;
var opts = arguments[2] === undefined ? {} : arguments[2];
var opts = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

@@ -75,9 +88,17 @@ _classCallCheck(this, Cursor);

// Checking whether the cursor is a watcher
this._watch = opts.watch;
this._watchedPaths = opts.watch && (!_type2['default'].array(opts.watch) ? Object.keys(opts.watch).map(function (k) {
return opts.watch[k];
}) : opts.watch);
if (opts.watch) {
this._watch = (0, _helpers.shallowClone)(opts.watch);
if (this._watch) this.get = this.tree.project.bind(this.tree, this._watch);
// Normalizing path
for (var k in this._watch) {
if (this._watch[k] instanceof Cursor) this._watch[k] = this._watch[k].path;
} // Keeping track of watched paths
this._watchedPaths = opts.watch && (!_type2['default'].array(this._watch) ? Object.keys(this._watch).map(function (k) {
return _this._watch[k];
}) : this._watch);
// Overriding the cursor's get method
this.get = this.tree.project.bind(this.tree, this._watch);
}
// Checking whether the given path is dynamic or not

@@ -182,4 +203,2 @@ this._dynamicPath = _type2['default'].dynamicPath(this.path);

_inherits(Cursor, _Emitter);
_createClass(Cursor, [{

@@ -268,3 +287,3 @@ key: 'isRoot',

value: function up() {
if (this.solvedPath && !this.isRoot()) return this.tree.select(this.path.slice(0, -1));else return null;
if (!this.isRoot()) return this.tree.select(this.path.slice(0, -1));else return null;
}

@@ -280,2 +299,4 @@ }, {

value: function down() {
checkPossibilityOfDynamicTraversal('down', this.solvedPath);
if (!(this._get().data instanceof Array)) throw Error('Baobab.Cursor.down: cannot go down on a non-list type.');

@@ -295,2 +316,4 @@

value: function left() {
checkPossibilityOfDynamicTraversal('left', this.solvedPath);
var last = +this.solvedPath[this.solvedPath.length - 1];

@@ -312,2 +335,4 @@

value: function right() {
checkPossibilityOfDynamicTraversal('right', this.solvedPath);
var last = +this.solvedPath[this.solvedPath.length - 1];

@@ -331,2 +356,4 @@

value: function leftmost() {
checkPossibilityOfDynamicTraversal('leftmost', this.solvedPath);
var last = +this.solvedPath[this.solvedPath.length - 1];

@@ -348,2 +375,4 @@

value: function rightmost() {
checkPossibilityOfDynamicTraversal('rightmost', this.solvedPath);
var last = +this.solvedPath[this.solvedPath.length - 1];

@@ -368,2 +397,4 @@

value: function map(fn, scope) {
checkPossibilityOfDynamicTraversal('map', this.solvedPath);
var array = this._get().data,

@@ -397,7 +428,10 @@ l = arguments.length;

value: function _get() {
var path = arguments[0] === undefined ? [] : arguments[0];
var path = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
var fullPath = this.solvedPath.concat(path),
data = (0, _helpers.getIn)(this.tree.data, fullPath, this.tree._computedDataIndex, this.tree.options);
var fullPath = this.solvedPath && this.solvedPath.concat(path);
var data = undefined;
if (!fullPath) data = undefined;else data = (0, _helpers.getIn)(this.tree.data, fullPath, this.tree._computedDataIndex, this.tree.options);
return { data: data, solvedPath: fullPath };

@@ -410,7 +444,5 @@ }

* Method used to get data from the tree. Will fire a `get` event from the
* tree so that the user may sometimes react upon it to fecth data, for
* tree so that the user may sometimes react upon it to fetch data, for
* instance.
*
* @todo: check path validity
*
* Arity (1):

@@ -435,3 +467,3 @@ * @param {path} path - Path to get in the tree.

// Emitting the event
this.tree.emit('get', { data: data, path: solvedPath });
if (solvedPath) this.tree.emit('get', { data: data, path: solvedPath });

@@ -540,3 +572,3 @@ return data;

value: function undo() {
var steps = arguments[0] === undefined ? 1 : arguments[0];
var steps = arguments.length <= 0 || arguments[0] === undefined ? 1 : arguments[0];

@@ -719,7 +751,6 @@ if (!this.state.recording) throw new Error('Baobab.Cursor.undo: cursor is not recording.');

makeSetter('push');
makeSetter('append', _type2['default'].array);
makeSetter('concat', _type2['default'].array);
makeSetter('unshift');
makeSetter('prepend', _type2['default'].array);
makeSetter('splice', _type2['default'].array);
makeSetter('merge', _type2['default'].object);
module.exports = exports['default'];

@@ -29,2 +29,6 @@ /**

var _facet = require('./facet');
var _facet2 = _interopRequireDefault(_facet);
var _type = require('./type');

@@ -313,2 +317,33 @@

/**
* Function used to solve a computed data mask by recursively walking a tree
* and patching it.
*
* @param {boolean} immutable - Is the data immutable?
* @param {mixed} data - Data to patch.
* @param {object} mask - Computed data mask.
* @param {object} [parent] - Parent object in the iteration.
* @param {string} [lastKey] - Current value's key in parent.
*/
function solveMask(immutable, data, mask, parent, lastKey) {
for (var k in mask) {
if (k[0] === '$') {
// Patching
data[k] = mask[k].get();
if (immutable) deepFreeze(parent);
} else {
if (immutable) {
data[k] = shallowClone(data[k]);
if (parent) freeze(parent);
}
solveMask(immutable, data[k], mask[k], data, k);
}
}
return data;
}
/**
* Function retrieving nested data within the given object and according to

@@ -327,4 +362,4 @@ * the given path.

function getIn(object, path) {
var mask = arguments[2] === undefined ? null : arguments[2];
var opts = arguments[3] === undefined ? {} : arguments[3];
var mask = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
var opts = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];

@@ -357,2 +392,4 @@ path = path || [];

cm = null;
if (opts.immutable) deepFreeze(c);
} else {

@@ -367,25 +404,6 @@ c = c[path[i]];

// If the mask is still relevant, we continue until we solved computed data
// completely
// If the mask is still relevant, we solve it down to the leaves
if (cm && Object.keys(cm).length) {
(function () {
// TODO: optimize, this is hardly performant
c = deepClone(c);
var walk = function walk(d, m) {
for (var k in m) {
if (k[0] === '$') {
d[k] = m[k].get();
} else {
walk(d[k], m[k]);
}
}
};
walk(c, cm);
// Freezing again if immutable
if (opts.immutable) deepFreeze(c);
})();
var patchedData = solveMask(opts.immutable, { root: c }, { root: cm });
c = patchedData.root;
}

@@ -435,2 +453,4 @@

* be used by Baobab's internal and would be unsuited in any other case.
* Note 4): this function will release any facet found on its path to the
* leaves for cleanup reasons.
*

@@ -460,2 +480,6 @@ * @param {boolean} deep - Whether the merge should be deep or not.

} else {
// Releasing
if (o[k] instanceof _facet2['default']) o[k].release();
o[k] = t[k];

@@ -541,2 +565,4 @@ }

idx = index(c, path[i]);
if (! ~idx) return null;
solvedPath.push(idx);

@@ -550,2 +576,4 @@ c = c[idx];

});
if (! ~idx) return null;
solvedPath.push(idx);

@@ -552,0 +580,0 @@ c = c[idx];

@@ -195,3 +195,3 @@ /**

// Ordered by likeliness
var VALID_OPERATIONS = ['set', 'apply', 'push', 'unshift', 'append', 'prepend', 'merge', 'splice', 'unset'];
var VALID_OPERATIONS = ['set', 'apply', 'push', 'unshift', 'concat', 'merge', 'splice', 'unset'];

@@ -198,0 +198,0 @@ type.operationType = function (string) {

@@ -40,3 +40,3 @@ /**

function update(data, path, operation) {
var opts = arguments[3] === undefined ? {} : arguments[3];
var opts = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3];
var operationType = operation.type;

@@ -102,6 +102,6 @@ var value = operation.value;

/**
* Append
* Concat
*/
else if (operationType === 'append') {
if (!_type2['default'].array(p[s])) throw err('append', 'array', currentPath);
else if (operationType === 'concat') {
if (!_type2['default'].array(p[s])) throw err('concat', 'array', currentPath);

@@ -112,11 +112,2 @@ p[s] = p[s].concat(value);

/**
* Prepend
*/
else if (operationType === 'prepend') {
if (!_type2['default'].array(p[s])) throw err('prepend', 'array', currentPath);
p[s] = value.concat(p[s]);
}
/**
* Splice

@@ -123,0 +114,0 @@ */

{
"name": "baobab",
"version": "2.0.0-dev3",
"version": "2.0.0-dev4",
"description": "JavaScript persistent data tree with cursors.",

@@ -5,0 +5,0 @@ "main": "./dist/baobab.js",

@@ -505,3 +505,6 @@ [![Build Status](https://travis-ci.org/Yomguithereal/baobab.svg)](https://travis-ci.org/Yomguithereal/baobab)

listCursor.select(1).down().left().get();
listCursor.select(1).down().right().get();
>>> 4
listCursor.select(1).down().right().left().get();
>>> 3

@@ -508,0 +511,0 @@

@@ -115,6 +115,5 @@ /**

[
'append',
'apply',
'concat',
'get',
'prepend',
'push',

@@ -139,7 +138,6 @@ 'merge',

* @param {array} [path] - Path to the modified node.
* @param {string} [operation] - Type of the applied operation.
* @param {mixed} [node] - The new node.
* @return {Baobab} - The tree itself for chaining purposes.
*/
_refreshComputedDataIndex(path, operation, node) {
_refreshComputedDataIndex(path, node) {

@@ -181,2 +179,7 @@ // Refreshing the whole tree

}
// else {
// // Walk the affected leaf
// return walk(node, path);
// }
}

@@ -273,2 +276,6 @@

// Refreshing facet index
// TODO: provide a setting to disable this or at least selectively for perf
this._refreshComputedDataIndex(solvedPath, node);
// Updating data and transaction

@@ -283,5 +290,4 @@ this.data = data;

// Should we let the user commit?
if (!this.options.autoCommit) {
if (!this.options.autoCommit)
return node;
}

@@ -418,3 +424,3 @@ // Should we update asynchronously?

Object.defineProperty(Baobab, 'version', {
value: '2.0.0-dev3'
value: '2.0.0-dev4'
});

@@ -421,0 +427,0 @@

@@ -16,2 +16,3 @@ /**

makeError,
shallowClone,
solvePath,

@@ -21,3 +22,20 @@ solveUpdate

/**
* Traversal helper function for dynamic cursors. Will throw a legible error
* if traversal is not possible.
*
* @param {string} method - The method name, to create a correct error msg.
* @param {array} solvedPath - The cursor's solved path.
*/
function checkPossibilityOfDynamicTraversal(method, solvedPath) {
if (!solvedPath)
throw makeError(
`Baobab.Cursor.${method}: ` +
`cannot use ${method} on an unresolved dynamic path.`,
{path: solvedPath}
);
}
/**
* Cursor class

@@ -55,9 +73,18 @@ *

// Checking whether the cursor is a watcher
this._watch = opts.watch;
this._watchedPaths = opts.watch && (!type.array(opts.watch) ?
Object.keys(opts.watch).map(k => opts.watch[k]) :
opts.watch);
if (opts.watch) {
this._watch = shallowClone(opts.watch);
if (this._watch)
// Normalizing path
for (let k in this._watch)
if (this._watch[k] instanceof Cursor)
this._watch[k] = this._watch[k].path;
// Keeping track of watched paths
this._watchedPaths = opts.watch && (!type.array(this._watch) ?
Object.keys(this._watch).map(k => this._watch[k]) :
this._watch);
// Overriding the cursor's get method
this.get = this.tree.project.bind(this.tree, this._watch);
}

@@ -247,3 +274,3 @@ // Checking whether the given path is dynamic or not

up() {
if (this.solvedPath && !this.isRoot())
if (!this.isRoot())
return this.tree.select(this.path.slice(0, -1));

@@ -260,2 +287,4 @@ else

down() {
checkPossibilityOfDynamicTraversal('down', this.solvedPath);
if (!(this._get().data instanceof Array))

@@ -274,2 +303,4 @@ throw Error('Baobab.Cursor.down: cannot go down on a non-list type.');

left() {
checkPossibilityOfDynamicTraversal('left', this.solvedPath);
const last = +this.solvedPath[this.solvedPath.length - 1];

@@ -292,2 +323,4 @@

right() {
checkPossibilityOfDynamicTraversal('right', this.solvedPath);
const last = +this.solvedPath[this.solvedPath.length - 1];

@@ -311,2 +344,4 @@

leftmost() {
checkPossibilityOfDynamicTraversal('leftmost', this.solvedPath);
const last = +this.solvedPath[this.solvedPath.length - 1];

@@ -327,2 +362,4 @@

rightmost() {
checkPossibilityOfDynamicTraversal('rightmost', this.solvedPath);
const last = +this.solvedPath[this.solvedPath.length - 1];

@@ -348,2 +385,4 @@

map(fn, scope) {
checkPossibilityOfDynamicTraversal('map', this.solvedPath);
let array = this._get().data,

@@ -381,10 +420,16 @@ l = arguments.length;

_get(path=[]) {
const fullPath = this.solvedPath.concat(path),
data = getIn(
this.tree.data,
fullPath,
this.tree._computedDataIndex,
this.tree.options
);
const fullPath = this.solvedPath && this.solvedPath.concat(path);
let data;
if (!fullPath)
data = undefined;
else
data = getIn(
this.tree.data,
fullPath,
this.tree._computedDataIndex,
this.tree.options
);
return {data, solvedPath: fullPath};

@@ -395,7 +440,5 @@ }

* Method used to get data from the tree. Will fire a `get` event from the
* tree so that the user may sometimes react upon it to fecth data, for
* tree so that the user may sometimes react upon it to fetch data, for
* instance.
*
* @todo: check path validity
*
* Arity (1):

@@ -418,3 +461,4 @@ * @param {path} path - Path to get in the tree.

// Emitting the event
this.tree.emit('get', {data, path: solvedPath});
if (solvedPath)
this.tree.emit('get', {data, path: solvedPath});

@@ -692,6 +736,5 @@ return data;

makeSetter('push');
makeSetter('append', type.array);
makeSetter('concat', type.array);
makeSetter('unshift');
makeSetter('prepend', type.array);
makeSetter('splice', type.array);
makeSetter('merge', type.object);

@@ -7,2 +7,3 @@ /**

*/
import Facet from './facet';
import type from './type';

@@ -290,2 +291,36 @@

/**
* Function used to solve a computed data mask by recursively walking a tree
* and patching it.
*
* @param {boolean} immutable - Is the data immutable?
* @param {mixed} data - Data to patch.
* @param {object} mask - Computed data mask.
* @param {object} [parent] - Parent object in the iteration.
* @param {string} [lastKey] - Current value's key in parent.
*/
function solveMask(immutable, data, mask, parent, lastKey) {
for (let k in mask) {
if (k[0] === '$') {
// Patching
data[k] = mask[k].get();
if (immutable)
deepFreeze(parent);
}
else {
if (immutable) {
data[k] = shallowClone(data[k]);
if (parent)
freeze(parent);
}
solveMask(immutable, data[k], mask[k], data, k);
}
}
return data;
}
/**
* Function retrieving nested data within the given object and according to

@@ -332,2 +367,5 @@ * the given path.

cm = null;
if (opts.immutable)
deepFreeze(c);
}

@@ -344,25 +382,6 @@ else {

// If the mask is still relevant, we continue until we solved computed data
// completely
// If the mask is still relevant, we solve it down to the leaves
if (cm && Object.keys(cm).length) {
// TODO: optimize, this is hardly performant
c = deepClone(c);
const walk = (d, m) => {
for (let k in m) {
if (k[0] === '$') {
d[k] = m[k].get();
}
else {
walk(d[k], m[k]);
}
}
};
walk(c, cm);
// Freezing again if immutable
if (opts.immutable)
deepFreeze(c);
let patchedData = solveMask(opts.immutable, {root: c}, {root: cm});
c = patchedData.root;
}

@@ -412,2 +431,4 @@

* be used by Baobab's internal and would be unsuited in any other case.
* Note 4): this function will release any facet found on its path to the
* leaves for cleanup reasons.
*

@@ -435,2 +456,7 @@ * @param {boolean} deep - Whether the merge should be deep or not.

else {
// Releasing
if (o[k] instanceof Facet)
o[k].release();
o[k] = t[k];

@@ -517,2 +543,5 @@ }

idx = index(c, path[i]);
if (!~idx)
return null;
solvedPath.push(idx);

@@ -526,2 +555,5 @@ c = c[idx];

idx = index(c, e => compare(e, path[i]));
if (!~idx)
return null;
solvedPath.push(idx);

@@ -528,0 +560,0 @@ c = c[idx];

@@ -200,4 +200,3 @@ /**

'unshift',
'append',
'prepend',
'concat',
'merge',

@@ -204,0 +203,0 @@ 'splice',

@@ -106,8 +106,8 @@ /**

/**
* Append
* Concat
*/
else if (operationType === 'append') {
else if (operationType === 'concat') {
if (!type.array(p[s]))
throw err(
'append',
'concat',
'array',

@@ -121,16 +121,2 @@ currentPath

/**
* Prepend
*/
else if (operationType === 'prepend') {
if (!type.array(p[s]))
throw err(
'prepend',
'array',
currentPath
);
p[s] = value.concat(p[s]);
}
/**
* Splice

@@ -137,0 +123,0 @@ */

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc