Comparing version 2.5.2 to 2.5.3
# Changelog | ||
## v2.5.3 | ||
* Refreshing the library's build to fix `babel` issues when consuming the library. | ||
## v2.5.2 | ||
@@ -4,0 +8,0 @@ |
@@ -1,47 +0,41 @@ | ||
'use strict'; | ||
"use strict"; | ||
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 _emmett = _interopRequireDefault(require("emmett")); | ||
var _emmett = require('emmett'); | ||
var _cursor = _interopRequireDefault(require("./cursor")); | ||
var _emmett2 = _interopRequireDefault(_emmett); | ||
var _monkey = require("./monkey"); | ||
var _cursor = require('./cursor'); | ||
var _watcher = _interopRequireDefault(require("./watcher")); | ||
var _cursor2 = _interopRequireDefault(_cursor); | ||
var _type = _interopRequireDefault(require("./type")); | ||
var _monkey = require('./monkey'); | ||
var _update2 = _interopRequireDefault(require("./update")); | ||
var _watcher = require('./watcher'); | ||
var helpers = _interopRequireWildcard(require("./helpers")); | ||
var _watcher2 = _interopRequireDefault(_watcher); | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } | ||
var _type = require('./type'); | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var _type2 = _interopRequireDefault(_type); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _update2 = require('./update'); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _update3 = _interopRequireDefault(_update2); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _helpers = require('./helpers'); | ||
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); } } | ||
var helpers = _interopRequireWildcard(_helpers); | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** | ||
* Baobab Data Structure | ||
* ====================== | ||
* | ||
* A handy data tree with cursors. | ||
*/ | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var arrayFrom = helpers.arrayFrom, | ||
@@ -57,3 +51,2 @@ coercePath = helpers.coercePath, | ||
hashPath = helpers.hashPath; | ||
/** | ||
@@ -64,31 +57,21 @@ * Baobab defaults | ||
var DEFAULTS = { | ||
// Should the tree handle its transactions on its own? | ||
autoCommit: true, | ||
// Should the transactions be handled asynchronously? | ||
asynchronous: true, | ||
// Should the tree's data be immutable? | ||
immutable: true, | ||
// Should the monkeys be lazy? | ||
lazyMonkeys: true, | ||
// Should we evaluate monkeys? | ||
monkeyBusiness: true, | ||
// Should the tree be persistent? | ||
persistent: true, | ||
// Should the tree's update be pure? | ||
pure: true, | ||
// Validation specifications | ||
validate: null, | ||
// Validation behavior 'rollback' or 'notify' | ||
validationBehavior: 'rollback' | ||
}; | ||
/** | ||
@@ -110,26 +93,28 @@ * Baobab class | ||
var Baobab = function (_Emitter) { | ||
var Baobab = | ||
/*#__PURE__*/ | ||
function (_Emitter) { | ||
_inherits(Baobab, _Emitter); | ||
function Baobab(initialData, opts) { | ||
var _this; | ||
_classCallCheck(this, Baobab); | ||
// Setting initialData to an empty object if no data is provided by use | ||
var _this = _possibleConstructorReturn(this, (Baobab.__proto__ || Object.getPrototypeOf(Baobab)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Baobab).call(this)); // Setting initialData to an empty object if no data is provided by use | ||
if (arguments.length < 1) initialData = {}; | ||
if (arguments.length < 1) initialData = {}; // Checking whether given initial data is valid | ||
// Checking whether given initial data is valid | ||
if (!_type2.default.object(initialData) && !_type2.default.array(initialData)) throw makeError('Baobab: invalid data.', { data: initialData }); | ||
if (!_type["default"].object(initialData) && !_type["default"].array(initialData)) throw makeError('Baobab: invalid data.', { | ||
data: initialData | ||
}); // Merging given options with defaults | ||
// Merging given options with defaults | ||
_this.options = shallowMerge({}, DEFAULTS, opts); | ||
_this.options = shallowMerge({}, DEFAULTS, opts); // Disabling immutability & persistence if persistence if disabled | ||
// Disabling immutability & persistence if persistence if disabled | ||
if (!_this.options.persistent) { | ||
_this.options.immutable = false; | ||
_this.options.pure = false; | ||
} | ||
} // Privates | ||
// Privates | ||
_this._identity = '[object Baobab]'; | ||
@@ -142,33 +127,30 @@ _this._cursors = {}; | ||
_this._previousData = null; | ||
_this._data = initialData; | ||
_this._data = initialData; // Properties | ||
// Properties | ||
_this.root = new _cursor2.default(_this, [], 'λ'); | ||
delete _this.root.release; | ||
_this.root = new _cursor["default"](_assertThisInitialized(_this), [], 'λ'); | ||
delete _this.root.release; // Does the user want an immutable tree? | ||
// Does the user want an immutable tree? | ||
if (_this.options.immutable) deepFreeze(_this._data); | ||
if (_this.options.immutable) deepFreeze(_this._data); // Bootstrapping root cursor's getters and setters | ||
// Bootstrapping root cursor's getters and setters | ||
var bootstrap = function bootstrap(name) { | ||
_this[name] = function () { | ||
var r = this.root[name].apply(this.root, arguments); | ||
return r instanceof _cursor2.default ? this : r; | ||
return r instanceof _cursor["default"] ? this : r; | ||
}; | ||
}; | ||
['apply', 'clone', 'concat', 'deepClone', 'deepMerge', 'exists', 'get', 'push', 'merge', 'pop', 'project', 'serialize', 'set', 'shift', 'splice', 'unset', 'unshift'].forEach(bootstrap); | ||
['apply', 'clone', 'concat', 'deepClone', 'deepMerge', 'exists', 'get', 'push', 'merge', 'pop', 'project', 'serialize', 'set', 'shift', 'splice', 'unset', 'unshift'].forEach(bootstrap); // Registering the initial monkeys | ||
// Registering the initial monkeys | ||
if (_this.options.monkeyBusiness) { | ||
_this._refreshMonkeys(); | ||
} | ||
} // Initial validation | ||
// Initial validation | ||
var validationError = _this.validate(); | ||
if (validationError) throw Error('Baobab: invalid data.', { error: validationError }); | ||
if (validationError) throw Error('Baobab: invalid data.', { | ||
error: validationError | ||
}); | ||
return _this; | ||
} | ||
/** | ||
@@ -188,3 +170,3 @@ * Internal method used to refresh the tree's monkey register on every | ||
_createClass(Baobab, [{ | ||
key: '_refreshMonkeys', | ||
key: "_refreshMonkeys", | ||
value: function _refreshMonkeys(node, path, operation) { | ||
@@ -198,3 +180,5 @@ var _this2 = this; | ||
data.release(); | ||
(0, _update3.default)(_this2._monkeys, p, { type: 'unset' }, { | ||
(0, _update2["default"])(_this2._monkeys, p, { | ||
type: 'unset' | ||
}, { | ||
immutable: false, | ||
@@ -204,7 +188,6 @@ persistent: false, | ||
}); | ||
return; | ||
} | ||
if (_type2.default.object(data)) { | ||
if (_type["default"].object(data)) { | ||
for (var k in data) { | ||
@@ -219,8 +202,9 @@ clean(data[k], p.concat(k)); | ||
// Should we sit a monkey in the tree? | ||
if (data instanceof _monkey.MonkeyDefinition || data instanceof _monkey.Monkey) { | ||
var monkeyInstance = new _monkey.Monkey(_this2, p, data instanceof _monkey.Monkey ? data.definition : data); | ||
(0, _update3.default)(_this2._monkeys, p, { type: 'set', value: monkeyInstance }, { | ||
(0, _update2["default"])(_this2._monkeys, p, { | ||
type: 'set', | ||
value: monkeyInstance | ||
}, { | ||
immutable: false, | ||
@@ -230,8 +214,7 @@ persistent: false, | ||
}); | ||
return; | ||
} | ||
} // Object iteration | ||
// Object iteration | ||
if (_type2.default.object(data)) { | ||
if (_type["default"].object(data)) { | ||
for (var k in data) { | ||
@@ -241,14 +224,12 @@ walk(data[k], p.concat(k)); | ||
} | ||
}; | ||
}; // Walking the whole tree | ||
// Walking the whole tree | ||
if (!arguments.length) { | ||
walk(this._data); | ||
} else { | ||
var monkeysNode = getIn(this._monkeys, path).data; | ||
var monkeysNode = getIn(this._monkeys, path).data; // Is this required that we clean some already existing monkeys? | ||
// Is this required that we clean some already existing monkeys? | ||
if (monkeysNode) clean(monkeysNode, path); | ||
if (monkeysNode) clean(monkeysNode, path); // Let's walk the tree only from the updated point | ||
// Let's walk the tree only from the updated point | ||
if (operation !== 'unset') { | ||
@@ -261,3 +242,2 @@ walk(node, path); | ||
} | ||
/** | ||
@@ -270,15 +250,11 @@ * Method used to validate the tree's data. | ||
}, { | ||
key: 'validate', | ||
key: "validate", | ||
value: function validate(affectedPaths) { | ||
var _options = this.options, | ||
validate = _options.validate, | ||
behavior = _options.validationBehavior; | ||
var _this$options = this.options, | ||
validate = _this$options.validate, | ||
behavior = _this$options.validationBehavior; | ||
if (typeof validate !== 'function') return null; | ||
var error = validate.call(this, this._previousData, this._data, affectedPaths || [[]]); | ||
if (error instanceof Error) { | ||
if (behavior === 'rollback') { | ||
@@ -291,4 +267,5 @@ this._data = this._previousData; | ||
this.emit('invalid', { error: error }); | ||
this.emit('invalid', { | ||
error: error | ||
}); | ||
return error; | ||
@@ -299,3 +276,2 @@ } | ||
} | ||
/** | ||
@@ -315,35 +291,33 @@ * Method used to select data within the tree by creating a cursor. Cursors | ||
}, { | ||
key: 'select', | ||
key: "select", | ||
value: function select(path) { | ||
// If no path is given, we simply return the root | ||
path = path || []; | ||
path = path || []; // Variadic | ||
// Variadic | ||
if (arguments.length > 1) path = arrayFrom(arguments); | ||
if (arguments.length > 1) path = arrayFrom(arguments); // Checking that given path is valid | ||
// Checking that given path is valid | ||
if (!_type2.default.path(path)) throw makeError('Baobab.select: invalid path.', { path: path }); | ||
if (!_type["default"].path(path)) throw makeError('Baobab.select: invalid path.', { | ||
path: path | ||
}); // Casting to array | ||
// Casting to array | ||
path = [].concat(path); | ||
// Computing hash (done here because it would be too late to do it in the | ||
path = [].concat(path); // Computing hash (done here because it would be too late to do it in the | ||
// cursor's constructor since we need to hit the cursors' index first). | ||
var hash = hashPath(path); | ||
// Creating a new cursor or returning the already existing one for the | ||
var hash = hashPath(path); // Creating a new cursor or returning the already existing one for the | ||
// requested path. | ||
var cursor = this._cursors[hash]; | ||
if (!cursor) { | ||
cursor = new _cursor2.default(this, path, hash); | ||
cursor = new _cursor["default"](this, path, hash); | ||
this._cursors[hash] = cursor; | ||
} | ||
} // Emitting an event to notify that a part of the tree was selected | ||
// Emitting an event to notify that a part of the tree was selected | ||
this.emit('select', { path: path, cursor: cursor }); | ||
this.emit('select', { | ||
path: path, | ||
cursor: cursor | ||
}); | ||
return cursor; | ||
} | ||
/** | ||
@@ -361,3 +335,3 @@ * Method used to update the tree. Updates are simply expressed by a path, | ||
}, { | ||
key: 'update', | ||
key: "update", | ||
value: function update(path, operation) { | ||
@@ -368,93 +342,80 @@ var _this3 = this; | ||
path = coercePath(path); | ||
if (!_type["default"].operationType(operation.type)) throw makeError("Baobab.update: unknown operation type \"".concat(operation.type, "\"."), { | ||
operation: operation | ||
}); // Solving the given path | ||
if (!_type2.default.operationType(operation.type)) throw makeError('Baobab.update: unknown operation type "' + operation.type + '".', { operation: operation }); | ||
// Solving the given path | ||
var _getIn = getIn(this._data, path), | ||
solvedPath = _getIn.solvedPath, | ||
exists = _getIn.exists; | ||
exists = _getIn.exists; // If we couldn't solve the path, we throw | ||
// If we couldn't solve the path, we throw | ||
if (!solvedPath) throw makeError('Baobab.update: could not solve the given path.', { | ||
path: solvedPath | ||
}); | ||
}); // Read-only path? | ||
// Read-only path? | ||
var monkeyPath = _type2.default.monkeyPath(this._monkeys, solvedPath); | ||
var monkeyPath = _type["default"].monkeyPath(this._monkeys, solvedPath); | ||
if (monkeyPath && solvedPath.length > monkeyPath.length) throw makeError('Baobab.update: attempting to update a read-only path.', { | ||
path: solvedPath | ||
}); | ||
}); // We don't unset irrelevant paths | ||
// We don't unset irrelevant paths | ||
if (operation.type === 'unset' && !exists) return; | ||
if (operation.type === 'unset' && !exists) return; // If we merge data, we need to acknowledge monkeys | ||
// If we merge data, we need to acknowledge monkeys | ||
var realOperation = operation; | ||
if (/merge/i.test(operation.type)) { | ||
var monkeysNode = getIn(this._monkeys, solvedPath).data; | ||
if (_type2.default.object(monkeysNode)) { | ||
if (_type["default"].object(monkeysNode)) { | ||
// Cloning the operation not to create weird behavior for the user | ||
realOperation = shallowClone(realOperation); | ||
realOperation = shallowClone(realOperation); // Fetching the existing node in the current data | ||
// Fetching the existing node in the current data | ||
var currentNode = getIn(this._data, solvedPath).data; | ||
if (/deep/i.test(realOperation.type)) realOperation.value = deepMerge({}, deepMerge({}, currentNode, deepClone(monkeysNode)), realOperation.value);else realOperation.value = shallowMerge({}, deepMerge({}, currentNode, deepClone(monkeysNode)), realOperation.value); | ||
} | ||
} | ||
} // Stashing previous data if this is the frame's first update | ||
// Stashing previous data if this is the frame's first update | ||
if (!this._transaction.length) this._previousData = this._data; | ||
// Applying the operation | ||
var result = (0, _update3.default)(this._data, solvedPath, realOperation, this.options); | ||
if (!this._transaction.length) this._previousData = this._data; // Applying the operation | ||
var result = (0, _update2["default"])(this._data, solvedPath, realOperation, this.options); | ||
var data = result.data, | ||
node = result.node; | ||
node = result.node; // If because of purity, the update was moot, we stop here | ||
// If because of purity, the update was moot, we stop here | ||
if (!('data' in result)) return node; // If the operation is push, the affected path is slightly different | ||
if (!('data' in result)) return node; | ||
// If the operation is push, the affected path is slightly different | ||
var affectedPath = solvedPath.concat(operation.type === 'push' ? node.length - 1 : []); | ||
var hash = hashPath(affectedPath); // Updating data and transaction | ||
var hash = hashPath(affectedPath); | ||
// Updating data and transaction | ||
this._data = data; | ||
this._affectedPathsIndex[hash] = true; | ||
this._transaction.push(shallowMerge({}, operation, { path: affectedPath })); | ||
// Updating the monkeys | ||
this._transaction.push(shallowMerge({}, operation, { | ||
path: affectedPath | ||
})); // Updating the monkeys | ||
if (this.options.monkeyBusiness) { | ||
this._refreshMonkeys(node, solvedPath, operation.type); | ||
} | ||
} // Emitting a `write` event | ||
// Emitting a `write` event | ||
this.emit('write', { path: affectedPath }); | ||
// Should we let the user commit? | ||
if (!this.options.autoCommit) return node; | ||
this.emit('write', { | ||
path: affectedPath | ||
}); // Should we let the user commit? | ||
// Should we update asynchronously? | ||
if (!this.options.autoCommit) return node; // Should we update asynchronously? | ||
if (!this.options.asynchronous) { | ||
this.commit(); | ||
return node; | ||
} | ||
} // Updating asynchronously | ||
// Updating asynchronously | ||
if (!this._future) this._future = setTimeout(function () { | ||
return _this3.commit(); | ||
}, 0); | ||
}, 0); // Finally returning the affected node | ||
// Finally returning the affected node | ||
return node; | ||
} | ||
/** | ||
@@ -467,29 +428,21 @@ * Method committing the updates of the tree and firing the tree's events. | ||
}, { | ||
key: 'commit', | ||
key: "commit", | ||
value: function commit() { | ||
// Do not fire update if the transaction is empty | ||
if (!this._transaction.length) return this; | ||
if (!this._transaction.length) return this; // Clearing timeout if one was defined | ||
// Clearing timeout if one was defined | ||
if (this._future) this._future = clearTimeout(this._future); | ||
var affectedPaths = Object.keys(this._affectedPathsIndex).map(function (h) { | ||
return h !== 'λ' ? h.split('λ').slice(1) : []; | ||
}); | ||
}); // Is the tree still valid? | ||
// Is the tree still valid? | ||
var validationError = this.validate(affectedPaths); | ||
if (validationError) return this; // Caching to keep original references before we change them | ||
if (validationError) return this; | ||
// Caching to keep original references before we change them | ||
var transaction = this._transaction, | ||
previousData = this._previousData; | ||
this._affectedPathsIndex = {}; | ||
this._transaction = []; | ||
this._previousData = this._data; | ||
this._previousData = this._data; // Emitting update event | ||
// Emitting update event | ||
this.emit('update', { | ||
@@ -501,6 +454,4 @@ paths: affectedPaths, | ||
}); | ||
return this; | ||
} | ||
/** | ||
@@ -514,13 +465,9 @@ * Method returning a monkey at the given path or else `null`. | ||
}, { | ||
key: 'getMonkey', | ||
key: "getMonkey", | ||
value: function getMonkey(path) { | ||
path = coercePath(path); | ||
var monkey = getIn(this._monkeys, [].concat(path)).data; | ||
if (monkey instanceof _monkey.Monkey) return monkey; | ||
return null; | ||
} | ||
/** | ||
@@ -535,7 +482,6 @@ * Method used to watch a collection of paths within the tree. Very useful | ||
}, { | ||
key: 'watch', | ||
key: "watch", | ||
value: function watch(mapping) { | ||
return new _watcher2.default(this, mapping); | ||
return new _watcher["default"](this, mapping); | ||
} | ||
/** | ||
@@ -546,10 +492,7 @@ * Method releasing the tree and its attached data from memory. | ||
}, { | ||
key: 'release', | ||
key: "release", | ||
value: function release() { | ||
var k = void 0; | ||
var k; | ||
this.emit('release'); | ||
delete this.root; | ||
delete this._data; | ||
@@ -559,13 +502,12 @@ delete this._previousData; | ||
delete this._affectedPathsIndex; | ||
delete this._monkeys; | ||
delete this._monkeys; // Releasing cursors | ||
// Releasing cursors | ||
for (k in this._cursors) { | ||
this._cursors[k].release(); | ||
}delete this._cursors; | ||
} | ||
// Killing event emitter | ||
delete this._cursors; // Killing event emitter | ||
this.kill(); | ||
} | ||
/** | ||
@@ -578,7 +520,6 @@ * Overriding the `toJSON` method for convenient use with JSON.stringify. | ||
}, { | ||
key: 'toJSON', | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this.serialize(); | ||
} | ||
/** | ||
@@ -591,3 +532,3 @@ * Overriding the `toString` method for debugging purposes. | ||
}, { | ||
key: 'toString', | ||
key: "toString", | ||
value: function toString() { | ||
@@ -599,4 +540,3 @@ return this._identity; | ||
return Baobab; | ||
}(_emmett2.default); | ||
}(_emmett["default"]); | ||
/** | ||
@@ -608,3 +548,3 @@ * Monkey helper. | ||
Baobab.monkey = function () { | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
@@ -614,26 +554,25 @@ } | ||
if (!args.length) throw new Error('Baobab.monkey: missing definition.'); | ||
if (args.length === 1 && typeof args[0] !== 'function') return new _monkey.MonkeyDefinition(args[0]); | ||
return new _monkey.MonkeyDefinition(args); | ||
}; | ||
Baobab.dynamicNode = Baobab.monkey; | ||
/** | ||
* Exposing some internals for convenience | ||
*/ | ||
Baobab.Cursor = _cursor2.default; | ||
Baobab.Cursor = _cursor["default"]; | ||
Baobab.MonkeyDefinition = _monkey.MonkeyDefinition; | ||
Baobab.Monkey = _monkey.Monkey; | ||
Baobab.type = _type2.default; | ||
Baobab.type = _type["default"]; | ||
Baobab.helpers = helpers; | ||
/** | ||
* Version. | ||
*/ | ||
Baobab.VERSION = '2.5.2'; | ||
Baobab.VERSION = '2.5.3'; | ||
/** | ||
* Exporting. | ||
*/ | ||
module.exports = Baobab; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,31 +6,32 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports["default"] = void 0; | ||
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 _emmett = _interopRequireDefault(require("emmett")); | ||
var _emmett = require('emmett'); | ||
var _monkey = require("./monkey"); | ||
var _emmett2 = _interopRequireDefault(_emmett); | ||
var _type = _interopRequireDefault(require("./type")); | ||
var _monkey = require('./monkey'); | ||
var _helpers = require("./helpers"); | ||
var _type = require('./type'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _type2 = _interopRequireDefault(_type); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _helpers = require('./helpers'); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
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); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** | ||
* Baobab Cursors | ||
* =============== | ||
* | ||
* Cursors created by selecting some data within a Baobab tree. | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
/** | ||
@@ -44,5 +45,6 @@ * Traversal helper function for dynamic cursors. Will throw a legible error | ||
function checkPossibilityOfDynamicTraversal(method, solvedPath) { | ||
if (!solvedPath) throw (0, _helpers.makeError)('Baobab.Cursor.' + method + ': ' + ('cannot use ' + method + ' on an unresolved dynamic path.'), { path: solvedPath }); | ||
if (!solvedPath) throw (0, _helpers.makeError)("Baobab.Cursor.".concat(method, ": ") + "cannot use ".concat(method, " on an unresolved dynamic path."), { | ||
path: solvedPath | ||
}); | ||
} | ||
/** | ||
@@ -57,23 +59,24 @@ * Cursor class | ||
var Cursor = function (_Emitter) { | ||
var Cursor = | ||
/*#__PURE__*/ | ||
function (_Emitter) { | ||
_inherits(Cursor, _Emitter); | ||
function Cursor(tree, path, hash) { | ||
var _this; | ||
_classCallCheck(this, Cursor); | ||
// If no path were to be provided, we fallback to an empty path (root) | ||
var _this = _possibleConstructorReturn(this, (Cursor.__proto__ || Object.getPrototypeOf(Cursor)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Cursor).call(this)); // If no path were to be provided, we fallback to an empty path (root) | ||
path = path || []; | ||
path = path || []; // Privates | ||
// Privates | ||
_this._identity = '[object Cursor]'; | ||
_this._archive = null; | ||
_this._archive = null; // Properties | ||
// Properties | ||
_this.tree = tree; | ||
_this.path = path; | ||
_this.hash = hash; | ||
_this.hash = hash; // State | ||
// State | ||
_this.state = { | ||
@@ -83,12 +86,8 @@ killed: false, | ||
undoing: false | ||
}; | ||
}; // Checking whether the given path is dynamic or not | ||
// Checking whether the given path is dynamic or not | ||
_this._dynamicPath = _type2.default.dynamicPath(_this.path); | ||
_this._dynamicPath = _type["default"].dynamicPath(_this.path); // Checking whether the given path will meet a monkey | ||
// Checking whether the given path will meet a monkey | ||
_this._monkeyPath = _type2.default.monkeyPath(_this.tree._monkeys, _this.path); | ||
_this._monkeyPath = _type["default"].monkeyPath(_this.tree._monkeys, _this.path); | ||
if (!_this._dynamicPath) _this.solvedPath = _this.path;else _this.solvedPath = (0, _helpers.getIn)(_this.tree._data, _this.path).solvedPath; | ||
/** | ||
@@ -100,10 +99,8 @@ * Listener bound to the tree's writes so that cursors with dynamic paths | ||
*/ | ||
_this._writeHandler = function (_ref) { | ||
var data = _ref.data; | ||
if (_this.state.killed || !(0, _helpers.solveUpdate)([data.path], _this._getComparedPaths())) return; | ||
_this.solvedPath = (0, _helpers.getIn)(_this.tree._data, _this.path).solvedPath; | ||
}; | ||
/** | ||
@@ -118,4 +115,6 @@ * Function in charge of actually trigger the cursor's updates and | ||
*/ | ||
var fireUpdate = function fireUpdate(previousData) { | ||
var self = _this; | ||
var self = _assertThisInitialized(_this); | ||
@@ -126,14 +125,12 @@ var eventData = { | ||
}, | ||
get currentData() { | ||
return self.get(); | ||
} | ||
}; | ||
if (_this.state.recording && !_this.state.undoing) _this.archive.add(eventData.previousData); | ||
_this.state.undoing = false; | ||
return _this.emit('update', eventData); | ||
}; | ||
/** | ||
@@ -149,2 +146,4 @@ * Listener bound to the tree's updates and determining whether the | ||
*/ | ||
_this._updateHandler = function (event) { | ||
@@ -156,32 +155,29 @@ if (_this.state.killed) return; | ||
previousData = _event$data.previousData, | ||
update = fireUpdate.bind(_this, previousData), | ||
update = fireUpdate.bind(_assertThisInitialized(_this), previousData), | ||
comparedPaths = _this._getComparedPaths(); | ||
if ((0, _helpers.solveUpdate)(paths, comparedPaths)) return update(); | ||
}; | ||
}; // Lazy binding | ||
// Lazy binding | ||
var bound = false; | ||
_this._lazyBind = function () { | ||
if (bound) return; | ||
bound = true; | ||
if (_this._dynamicPath) _this.tree.on('write', _this._writeHandler); | ||
return _this.tree.on('update', _this._updateHandler); | ||
}; | ||
}; // If the path is dynamic, we actually need to listen to the tree | ||
// If the path is dynamic, we actually need to listen to the tree | ||
if (_this._dynamicPath) { | ||
_this._lazyBind(); | ||
} else { | ||
// Overriding the emitter `on` and `once` methods | ||
_this.on = (0, _helpers.before)(_this._lazyBind, _this.on.bind(_this)); | ||
_this.once = (0, _helpers.before)(_this._lazyBind, _this.once.bind(_this)); | ||
_this.on = (0, _helpers.before)(_this._lazyBind, _this.on.bind(_assertThisInitialized(_this))); | ||
_this.once = (0, _helpers.before)(_this._lazyBind, _this.once.bind(_assertThisInitialized(_this))); | ||
} | ||
return _this; | ||
} | ||
/** | ||
@@ -201,11 +197,8 @@ * Internal helpers | ||
_createClass(Cursor, [{ | ||
key: '_getComparedPaths', | ||
key: "_getComparedPaths", | ||
value: function _getComparedPaths() { | ||
// Checking whether we should keep track of some dependencies | ||
var additionalPaths = this._monkeyPath ? (0, _helpers.getIn)(this.tree._monkeys, this._monkeyPath).data.relatedPaths() : []; | ||
return [this.solvedPath].concat(additionalPaths); | ||
} | ||
/** | ||
@@ -223,7 +216,6 @@ * Predicates | ||
}, { | ||
key: 'isRoot', | ||
key: "isRoot", | ||
value: function isRoot() { | ||
return !this.path.length; | ||
} | ||
/** | ||
@@ -236,7 +228,6 @@ * Method returning whether the cursor is at leaf level. | ||
}, { | ||
key: 'isLeaf', | ||
key: "isLeaf", | ||
value: function isLeaf() { | ||
return _type2.default.primitive(this._get().data); | ||
return _type["default"].primitive(this._get().data); | ||
} | ||
/** | ||
@@ -249,7 +240,6 @@ * Method returning whether the cursor is at branch level. | ||
}, { | ||
key: 'isBranch', | ||
key: "isBranch", | ||
value: function isBranch() { | ||
return !this.isRoot() && !this.isLeaf(); | ||
} | ||
/** | ||
@@ -267,7 +257,6 @@ * Traversal Methods | ||
}, { | ||
key: 'root', | ||
key: "root", | ||
value: function root() { | ||
return this.tree.select(); | ||
} | ||
/** | ||
@@ -286,9 +275,7 @@ * Method selecting a subpath as a new cursor. | ||
}, { | ||
key: 'select', | ||
key: "select", | ||
value: function select(path) { | ||
if (arguments.length > 1) path = (0, _helpers.arrayFrom)(arguments); | ||
return this.tree.select(this.path.concat(path)); | ||
} | ||
/** | ||
@@ -302,9 +289,7 @@ * Method returning the parent node of the cursor or else `null` if the | ||
}, { | ||
key: 'up', | ||
key: "up", | ||
value: function up() { | ||
if (!this.isRoot()) return this.tree.select(this.path.slice(0, -1)); | ||
return null; | ||
} | ||
/** | ||
@@ -317,11 +302,8 @@ * Method returning the child node of the cursor. | ||
}, { | ||
key: 'down', | ||
key: "down", | ||
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.'); | ||
return this.tree.select(this.solvedPath.concat(0)); | ||
} | ||
/** | ||
@@ -335,13 +317,9 @@ * Method returning the left sibling node of the cursor if this one is | ||
}, { | ||
key: 'left', | ||
key: "left", | ||
value: function left() { | ||
checkPossibilityOfDynamicTraversal('left', this.solvedPath); | ||
var last = +this.solvedPath[this.solvedPath.length - 1]; | ||
if (isNaN(last)) throw Error('Baobab.Cursor.left: cannot go left on a non-list type.'); | ||
return last ? this.tree.select(this.solvedPath.slice(0, -1).concat(last - 1)) : null; | ||
} | ||
/** | ||
@@ -355,15 +333,10 @@ * Method returning the right sibling node of the cursor if this one is | ||
}, { | ||
key: 'right', | ||
key: "right", | ||
value: function right() { | ||
checkPossibilityOfDynamicTraversal('right', this.solvedPath); | ||
var last = +this.solvedPath[this.solvedPath.length - 1]; | ||
if (isNaN(last)) throw Error('Baobab.Cursor.right: cannot go right on a non-list type.'); | ||
if (last + 1 === this.up()._get().data.length) return null; | ||
return this.tree.select(this.solvedPath.slice(0, -1).concat(last + 1)); | ||
} | ||
/** | ||
@@ -377,13 +350,9 @@ * Method returning the leftmost sibling node of the cursor if this one is | ||
}, { | ||
key: 'leftmost', | ||
key: "leftmost", | ||
value: function leftmost() { | ||
checkPossibilityOfDynamicTraversal('leftmost', this.solvedPath); | ||
var last = +this.solvedPath[this.solvedPath.length - 1]; | ||
if (isNaN(last)) throw Error('Baobab.Cursor.leftmost: cannot go left on a non-list type.'); | ||
return this.tree.select(this.solvedPath.slice(0, -1).concat(0)); | ||
} | ||
/** | ||
@@ -397,8 +366,6 @@ * Method returning the rightmost sibling node of the cursor if this one is | ||
}, { | ||
key: 'rightmost', | ||
key: "rightmost", | ||
value: function rightmost() { | ||
checkPossibilityOfDynamicTraversal('rightmost', this.solvedPath); | ||
var last = +this.solvedPath[this.solvedPath.length - 1]; | ||
if (isNaN(last)) throw Error('Baobab.Cursor.rightmost: cannot go right on a non-list type.'); | ||
@@ -410,3 +377,2 @@ | ||
} | ||
/** | ||
@@ -421,3 +387,3 @@ * Method mapping the children nodes of the cursor. | ||
}, { | ||
key: 'map', | ||
key: "map", | ||
value: function map(fn, scope) { | ||
@@ -429,4 +395,3 @@ checkPossibilityOfDynamicTraversal('map', this.solvedPath); | ||
if (!_type2.default.array(array)) throw Error('baobab.Cursor.map: cannot map a non-list type.'); | ||
if (!_type["default"].array(array)) throw Error('baobab.Cursor.map: cannot map a non-list type.'); | ||
return array.map(function (item, i) { | ||
@@ -436,3 +401,2 @@ return fn.call(l > 1 ? scope : this, this.select(i), i, array); | ||
} | ||
/** | ||
@@ -455,14 +419,15 @@ * Getter Methods | ||
}, { | ||
key: '_get', | ||
key: "_get", | ||
value: function _get() { | ||
var path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; | ||
if (!_type2.default.path(path)) throw (0, _helpers.makeError)('Baobab.Cursor.getters: invalid path.', { path: path }); | ||
if (!this.solvedPath) return { data: undefined, solvedPath: null, exists: false }; | ||
if (!_type["default"].path(path)) throw (0, _helpers.makeError)('Baobab.Cursor.getters: invalid path.', { | ||
path: path | ||
}); | ||
if (!this.solvedPath) return { | ||
data: undefined, | ||
solvedPath: null, | ||
exists: false | ||
}; | ||
return (0, _helpers.getIn)(this.tree._data, this.solvedPath.concat(path)); | ||
} | ||
/** | ||
@@ -482,11 +447,8 @@ * Method used to check whether a certain path exists in the tree starting | ||
}, { | ||
key: 'exists', | ||
key: "exists", | ||
value: function exists(path) { | ||
path = (0, _helpers.coercePath)(path); | ||
if (arguments.length > 1) path = (0, _helpers.arrayFrom)(arguments); | ||
return this._get(path).exists; | ||
} | ||
/** | ||
@@ -507,20 +469,19 @@ * Method used to get data from the tree. Will fire a `get` event from the | ||
}, { | ||
key: 'get', | ||
key: "get", | ||
value: function get(path) { | ||
path = (0, _helpers.coercePath)(path); | ||
if (arguments.length > 1) path = (0, _helpers.arrayFrom)(arguments); | ||
var _get2 = this._get(path), | ||
data = _get2.data, | ||
solvedPath = _get2.solvedPath; | ||
var _this$_get = this._get(path), | ||
data = _this$_get.data, | ||
solvedPath = _this$_get.solvedPath; // Emitting the event | ||
// Emitting the event | ||
this.tree.emit('get', { data: data, solvedPath: solvedPath, path: this.path.concat(path) }); | ||
this.tree.emit('get', { | ||
data: data, | ||
solvedPath: solvedPath, | ||
path: this.path.concat(path) | ||
}); | ||
return data; | ||
} | ||
/** | ||
@@ -539,9 +500,7 @@ * Method used to shallow clone data from the tree. | ||
}, { | ||
key: 'clone', | ||
key: "clone", | ||
value: function clone() { | ||
var data = this.get.apply(this, arguments); | ||
return (0, _helpers.shallowClone)(data); | ||
} | ||
/** | ||
@@ -560,9 +519,7 @@ * Method used to deep clone data from the tree. | ||
}, { | ||
key: 'deepClone', | ||
key: "deepClone", | ||
value: function deepClone() { | ||
var data = this.get.apply(this, arguments); | ||
return (0, _helpers.deepClone)(data); | ||
} | ||
/** | ||
@@ -585,14 +542,11 @@ * Method used to return raw data from the tree, by carefully avoiding | ||
}, { | ||
key: 'serialize', | ||
key: "serialize", | ||
value: function serialize(path) { | ||
path = (0, _helpers.coercePath)(path); | ||
if (arguments.length > 1) path = (0, _helpers.arrayFrom)(arguments); | ||
if (!_type2.default.path(path)) throw (0, _helpers.makeError)('Baobab.Cursor.getters: invalid path.', { path: path }); | ||
if (!_type["default"].path(path)) throw (0, _helpers.makeError)('Baobab.Cursor.getters: invalid path.', { | ||
path: path | ||
}); | ||
if (!this.solvedPath) return undefined; | ||
var fullPath = this.solvedPath.concat(path); | ||
var data = (0, _helpers.deepClone)((0, _helpers.getIn)(this.tree._data, fullPath).data), | ||
@@ -602,3 +556,3 @@ monkeys = (0, _helpers.getIn)(this.tree._monkeys, fullPath).data; | ||
var dropComputedData = function dropComputedData(d, m) { | ||
if (!_type2.default.object(m) || !_type2.default.object(d)) return; | ||
if (!_type["default"].object(m) || !_type["default"].object(d)) return; | ||
@@ -613,3 +567,2 @@ for (var k in m) { | ||
} | ||
/** | ||
@@ -623,5 +576,5 @@ * Method used to project some of the data at cursor onto a map or a list. | ||
}, { | ||
key: 'project', | ||
key: "project", | ||
value: function project(projection) { | ||
if (_type2.default.object(projection)) { | ||
if (_type["default"].object(projection)) { | ||
var data = {}; | ||
@@ -631,4 +584,6 @@ | ||
data[k] = this.get(projection[k]); | ||
}return data; | ||
} else if (_type2.default.array(projection)) { | ||
} | ||
return data; | ||
} else if (_type["default"].array(projection)) { | ||
var _data = []; | ||
@@ -638,8 +593,11 @@ | ||
_data.push(this.get(projection[i])); | ||
}return _data; | ||
} | ||
return _data; | ||
} | ||
throw (0, _helpers.makeError)('Baobab.Cursor.project: wrong projection.', { projection: projection }); | ||
throw (0, _helpers.makeError)('Baobab.Cursor.project: wrong projection.', { | ||
projection: projection | ||
}); | ||
} | ||
/** | ||
@@ -660,15 +618,11 @@ * History Methods | ||
}, { | ||
key: 'startRecording', | ||
key: "startRecording", | ||
value: function startRecording(maxRecords) { | ||
maxRecords = maxRecords || Infinity; | ||
if (maxRecords < 1) throw (0, _helpers.makeError)('Baobab.Cursor.startRecording: invalid max records.', { | ||
value: maxRecords | ||
}); | ||
this.state.recording = true; | ||
if (this.archive) return this; // Lazy binding | ||
if (this.archive) return this; | ||
// Lazy binding | ||
this._lazyBind(); | ||
@@ -679,3 +633,2 @@ | ||
} | ||
/** | ||
@@ -688,3 +641,3 @@ * Methods stopping to record the cursor's successive states. | ||
}, { | ||
key: 'stopRecording', | ||
key: "stopRecording", | ||
value: function stopRecording() { | ||
@@ -694,3 +647,2 @@ this.state.recording = false; | ||
} | ||
/** | ||
@@ -704,18 +656,12 @@ * Methods undoing n steps of the cursor's recorded states. | ||
}, { | ||
key: 'undo', | ||
key: "undo", | ||
value: function undo() { | ||
var steps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; | ||
if (!this.state.recording) throw new Error('Baobab.Cursor.undo: cursor is not recording.'); | ||
var record = this.archive.back(steps); | ||
if (!record) throw Error('Baobab.Cursor.undo: cannot find a relevant record.'); | ||
this.state.undoing = true; | ||
this.set(record); | ||
return this; | ||
} | ||
/** | ||
@@ -728,7 +674,6 @@ * Methods returning whether the cursor has a recorded history. | ||
}, { | ||
key: 'hasHistory', | ||
key: "hasHistory", | ||
value: function hasHistory() { | ||
return !!(this.archive && this.archive.get().length); | ||
} | ||
/** | ||
@@ -741,7 +686,6 @@ * Methods returning the cursor's history. | ||
}, { | ||
key: 'getHistory', | ||
key: "getHistory", | ||
value: function getHistory() { | ||
return this.archive ? this.archive.get() : []; | ||
} | ||
/** | ||
@@ -754,3 +698,3 @@ * Methods clearing the cursor's history. | ||
}, { | ||
key: 'clearHistory', | ||
key: "clearHistory", | ||
value: function clearHistory() { | ||
@@ -760,3 +704,2 @@ if (this.archive) this.archive.clear(); | ||
} | ||
/** | ||
@@ -772,24 +715,18 @@ * Releasing | ||
}, { | ||
key: 'release', | ||
key: "release", | ||
value: function release() { | ||
// Removing listeners on parent | ||
if (this._dynamicPath) this.tree.off('write', this._writeHandler); | ||
this.tree.off('update', this._updateHandler); // Unsubscribe from the parent | ||
this.tree.off('update', this._updateHandler); | ||
if (this.hash) delete this.tree._cursors[this.hash]; // Dereferencing | ||
// Unsubscribe from the parent | ||
if (this.hash) delete this.tree._cursors[this.hash]; | ||
// Dereferencing | ||
delete this.tree; | ||
delete this.path; | ||
delete this.solvedPath; | ||
delete this.archive; | ||
delete this.archive; // Killing emitter | ||
// Killing emitter | ||
this.kill(); | ||
this.state.killed = true; | ||
} | ||
/** | ||
@@ -807,7 +744,6 @@ * Output | ||
}, { | ||
key: 'toJSON', | ||
key: "toJSON", | ||
value: function toJSON() { | ||
return this.serialize(); | ||
} | ||
/** | ||
@@ -820,3 +756,3 @@ * Overriding the `toString` method for debugging purposes. | ||
}, { | ||
key: 'toString', | ||
key: "toString", | ||
value: function toString() { | ||
@@ -828,4 +764,3 @@ return this._identity; | ||
return Cursor; | ||
}(_emmett2.default); | ||
}(_emmett["default"]); | ||
/** | ||
@@ -840,3 +775,4 @@ * Method used to allow iterating over cursors containing list-type data. | ||
exports.default = Cursor; | ||
exports["default"] = Cursor; | ||
if (typeof Symbol === 'function' && typeof Symbol.iterator !== 'undefined') { | ||
@@ -846,9 +782,6 @@ Cursor.prototype[Symbol.iterator] = function () { | ||
if (!_type2.default.array(array)) throw Error('baobab.Cursor.@@iterate: cannot iterate a non-list type.'); | ||
if (!_type["default"].array(array)) throw Error('baobab.Cursor.@@iterate: cannot iterate a non-list type.'); | ||
var i = 0; | ||
var cursor = this, | ||
length = array.length; | ||
return { | ||
@@ -869,3 +802,2 @@ next: function next() { | ||
} | ||
/** | ||
@@ -877,4 +809,5 @@ * Setter Methods | ||
*/ | ||
// Not using a Set so that ES5 consumers don't pay a bundle size price | ||
// Not using a Set so that ES5 consumers don't pay a bundle size price | ||
var INTRANSITIVE_SETTERS = { | ||
@@ -885,3 +818,2 @@ unset: true, | ||
}; | ||
/** | ||
@@ -894,4 +826,4 @@ * Function creating a setter method for the Cursor class. | ||
*/ | ||
function makeSetter(name, typeChecker) { | ||
/** | ||
@@ -917,27 +849,27 @@ * Binding a setter method to the Cursor class and having the following | ||
Cursor.prototype[name] = function (path, value) { | ||
// We should warn the user if he applies to many arguments to the function | ||
if (arguments.length > 2) throw (0, _helpers.makeError)('Baobab.Cursor.' + name + ': too many arguments.'); | ||
if (arguments.length > 2) throw (0, _helpers.makeError)("Baobab.Cursor.".concat(name, ": too many arguments.")); // Handling arities | ||
// Handling arities | ||
if (arguments.length === 1 && !INTRANSITIVE_SETTERS[name]) { | ||
value = path; | ||
path = []; | ||
} | ||
} // Coerce path | ||
// Coerce path | ||
path = (0, _helpers.coercePath)(path); | ||
// Checking the path's validity | ||
if (!_type2.default.path(path)) throw (0, _helpers.makeError)('Baobab.Cursor.' + name + ': invalid path.', { path: path }); | ||
path = (0, _helpers.coercePath)(path); // Checking the path's validity | ||
// Checking the value's validity | ||
if (typeChecker && !typeChecker(value)) throw (0, _helpers.makeError)('Baobab.Cursor.' + name + ': invalid value.', { path: path, value: value }); | ||
if (!_type["default"].path(path)) throw (0, _helpers.makeError)("Baobab.Cursor.".concat(name, ": invalid path."), { | ||
path: path | ||
}); // Checking the value's validity | ||
// Checking the solvability of the cursor's dynamic path | ||
if (!this.solvedPath) throw (0, _helpers.makeError)('Baobab.Cursor.' + name + ': the dynamic path of the cursor cannot be solved.', { path: this.path }); | ||
if (typeChecker && !typeChecker(value)) throw (0, _helpers.makeError)("Baobab.Cursor.".concat(name, ": invalid value."), { | ||
path: path, | ||
value: value | ||
}); // Checking the solvability of the cursor's dynamic path | ||
var fullPath = this.solvedPath.concat(path); | ||
if (!this.solvedPath) throw (0, _helpers.makeError)("Baobab.Cursor.".concat(name, ": the dynamic path of the cursor cannot be solved."), { | ||
path: this.path | ||
}); | ||
var fullPath = this.solvedPath.concat(path); // Filing the update to the tree | ||
// Filing the update to the tree | ||
return this.tree.update(fullPath, { | ||
@@ -949,16 +881,17 @@ type: name, | ||
} | ||
/** | ||
* Making the necessary setters. | ||
*/ | ||
makeSetter('set'); | ||
makeSetter('unset'); | ||
makeSetter('apply', _type2.default.function); | ||
makeSetter('apply', _type["default"]["function"]); | ||
makeSetter('push'); | ||
makeSetter('concat', _type2.default.array); | ||
makeSetter('concat', _type["default"].array); | ||
makeSetter('unshift'); | ||
makeSetter('pop'); | ||
makeSetter('shift'); | ||
makeSetter('splice', _type2.default.splicer); | ||
makeSetter('merge', _type2.default.object); | ||
makeSetter('deepMerge', _type2.default.object); | ||
makeSetter('splice', _type["default"].splicer); | ||
makeSetter('merge', _type["default"].object); | ||
makeSetter('deepMerge', _type["default"].object); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,16 +6,2 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.uniqid = exports.deepMerge = exports.shallowMerge = exports.deepFreeze = exports.freeze = exports.deepClone = exports.shallowClone = exports.Archive = undefined; | ||
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 _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; }; }(); /* eslint eqeqeq: 0 */ | ||
/* eslint no-use-before-define: 0 */ | ||
/** | ||
* Baobab Helpers | ||
* =============== | ||
* | ||
* Miscellaneous helper functions. | ||
*/ | ||
exports.arrayFrom = arrayFrom; | ||
@@ -30,15 +16,19 @@ exports.before = before; | ||
exports.splice = splice; | ||
exports.uniqid = exports.deepMerge = exports.shallowMerge = exports.deepFreeze = exports.freeze = exports.deepClone = exports.shallowClone = exports.Archive = void 0; | ||
var _monkey = require('./monkey'); | ||
var _monkey = require("./monkey"); | ||
var _type = require('./type'); | ||
var _type = _interopRequireDefault(require("./type")); | ||
var _type2 = _interopRequireDefault(_type); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
var hasOwnProp = {}.hasOwnProperty; | ||
/** | ||
@@ -52,11 +42,12 @@ * Function returning the index of the first element of a list matching the | ||
*/ | ||
function index(a, fn) { | ||
var i = void 0, | ||
l = void 0; | ||
var i, l; | ||
for (i = 0, l = a.length; i < l; i++) { | ||
if (fn(a[i])) return i; | ||
} | ||
return -1; | ||
} | ||
/** | ||
@@ -68,13 +59,14 @@ * Efficient slice function used to clone arrays or parts of them. | ||
*/ | ||
function slice(array) { | ||
var newArray = new Array(array.length); | ||
var i, l; | ||
var i = void 0, | ||
l = void 0; | ||
for (i = 0, l = array.length; i < l; i++) { | ||
newArray[i] = array[i]; | ||
}return newArray; | ||
} | ||
return newArray; | ||
} | ||
/** | ||
@@ -87,3 +79,6 @@ * Archive abstraction | ||
var Archive = exports.Archive = function () { | ||
var Archive = | ||
/*#__PURE__*/ | ||
function () { | ||
function Archive(size) { | ||
@@ -95,3 +90,2 @@ _classCallCheck(this, Archive); | ||
} | ||
/** | ||
@@ -105,7 +99,6 @@ * Method retrieving the records. | ||
_createClass(Archive, [{ | ||
key: 'get', | ||
key: "get", | ||
value: function get() { | ||
return this.records; | ||
} | ||
/** | ||
@@ -119,12 +112,9 @@ * Method adding a record to the archive | ||
}, { | ||
key: 'add', | ||
key: "add", | ||
value: function add(record) { | ||
this.records.unshift(record); | ||
this.records.unshift(record); // If the number of records is exceeded, we truncate the records | ||
// If the number of records is exceeded, we truncate the records | ||
if (this.records.length > this.size) this.records.length = this.size; | ||
return this; | ||
} | ||
/** | ||
@@ -137,3 +127,3 @@ * Method clearing the records. | ||
}, { | ||
key: 'clear', | ||
key: "clear", | ||
value: function clear() { | ||
@@ -143,3 +133,2 @@ this.records = []; | ||
} | ||
/** | ||
@@ -153,6 +142,5 @@ * Method to go back in time. | ||
}, { | ||
key: 'back', | ||
key: "back", | ||
value: function back(steps) { | ||
var record = this.records[steps - 1]; | ||
if (record) this.records = this.records.slice(steps); | ||
@@ -165,3 +153,2 @@ return record; | ||
}(); | ||
/** | ||
@@ -176,6 +163,7 @@ * Function creating a real array from what should be an array but is not. | ||
exports.Archive = Archive; | ||
function arrayFrom(culprit) { | ||
return slice(culprit); | ||
} | ||
/** | ||
@@ -189,2 +177,4 @@ * Function decorating one function with another that will be called before the | ||
*/ | ||
function before(decorator, fn) { | ||
@@ -196,3 +186,2 @@ return function () { | ||
} | ||
/** | ||
@@ -205,7 +194,7 @@ * Function cloning the given regular expression. Supports `y` and `u` flags | ||
*/ | ||
function cloneRegexp(re) { | ||
var pattern = re.source; | ||
var flags = ''; | ||
if (re.global) flags += 'g'; | ||
@@ -216,6 +205,4 @@ if (re.multiline) flags += 'm'; | ||
if (re.unicode) flags += 'u'; | ||
return new RegExp(pattern, flags); | ||
} | ||
/** | ||
@@ -230,7 +217,8 @@ * Function cloning the given variable. | ||
*/ | ||
function cloner(deep, item) { | ||
if (!item || (typeof item === 'undefined' ? 'undefined' : _typeof(item)) !== 'object' || item instanceof Error || item instanceof _monkey.MonkeyDefinition || item instanceof _monkey.Monkey || 'ArrayBuffer' in global && item instanceof ArrayBuffer) return item; | ||
if (!item || _typeof(item) !== 'object' || item instanceof Error || item instanceof _monkey.MonkeyDefinition || item instanceof _monkey.Monkey || 'ArrayBuffer' in global && item instanceof ArrayBuffer) return item; // Array | ||
// Array | ||
if (_type2.default.array(item)) { | ||
if (_type["default"].array(item)) { | ||
if (deep) { | ||
@@ -241,23 +229,24 @@ var a = new Array(item.length); | ||
a[i] = cloner(true, item[i]); | ||
}return a; | ||
} | ||
return a; | ||
} | ||
return slice(item); | ||
} | ||
} // Date | ||
// Date | ||
if (item instanceof Date) return new Date(item.getTime()); | ||
// RegExp | ||
if (item instanceof RegExp) return cloneRegexp(item); | ||
if (item instanceof Date) return new Date(item.getTime()); // RegExp | ||
// Object | ||
if (_type2.default.object(item)) { | ||
var o = {}; | ||
if (item instanceof RegExp) return cloneRegexp(item); // Object | ||
// NOTE: could be possible to erase computed properties through `null`. | ||
if (_type["default"].object(item)) { | ||
var o = {}; // NOTE: could be possible to erase computed properties through `null`. | ||
var props = Object.getOwnPropertyNames(item); | ||
for (var _i = 0, _l = props.length; _i < _l; _i++) { | ||
var name = props[_i]; | ||
var k = Object.getOwnPropertyDescriptor(item, name); | ||
if (k.enumerable === true) { | ||
@@ -282,2 +271,3 @@ if (k.get && k.get.isLazyGetter) { | ||
} | ||
return o; | ||
@@ -288,11 +278,11 @@ } | ||
} | ||
/** | ||
* Exporting shallow and deep cloning functions. | ||
*/ | ||
var shallowClone = cloner.bind(null, false), | ||
deepClone = cloner.bind(null, true); | ||
exports.deepClone = deepClone; | ||
exports.shallowClone = shallowClone; | ||
exports.deepClone = deepClone; | ||
@@ -305,3 +295,2 @@ /** | ||
*/ | ||
function coercePath(target) { | ||
@@ -311,3 +300,2 @@ if (target || target === 0 || target === '') return target; | ||
} | ||
/** | ||
@@ -321,14 +309,15 @@ * Function comparing an object's properties to a given descriptive | ||
*/ | ||
function compare(object, description) { | ||
var ok = true, | ||
k = void 0; | ||
k; // If we reached here via a recursive call, object may be undefined because | ||
// not all items in a collection will have the same deep nesting structure. | ||
// If we reached here via a recursive call, object may be undefined because | ||
// not all items in a collection will have the same deep nesting structure. | ||
if (!object) return false; | ||
for (k in description) { | ||
if (_type2.default.object(description[k])) { | ||
if (_type["default"].object(description[k])) { | ||
ok = ok && compare(object[k], description[k]); | ||
} else if (_type2.default.array(description[k])) { | ||
} else if (_type["default"].array(description[k])) { | ||
ok = ok && !!~description[k].indexOf(object[k]); | ||
@@ -342,3 +331,2 @@ } else { | ||
} | ||
/** | ||
@@ -351,14 +339,12 @@ * Function freezing the given variable if possible. | ||
*/ | ||
function freezer(deep, o) { | ||
if ((typeof o === 'undefined' ? 'undefined' : _typeof(o)) !== 'object' || o === null || o instanceof _monkey.Monkey) return; | ||
if (_typeof(o) !== 'object' || o === null || o instanceof _monkey.Monkey) return; | ||
Object.freeze(o); | ||
if (!deep) return; | ||
if (Array.isArray(o)) { | ||
// Iterating through the elements | ||
var i = void 0, | ||
l = void 0; | ||
var i, l; | ||
@@ -369,12 +355,8 @@ for (i = 0, l = o.length; i < l; i++) { | ||
} else { | ||
var p = void 0, | ||
k = void 0; | ||
var p, k; | ||
for (k in o) { | ||
if (_type2.default.lazyGetter(o, k)) continue; | ||
if (_type["default"].lazyGetter(o, k)) continue; | ||
p = o[k]; | ||
if (!p || !hasOwnProp.call(o, k) || (typeof p === 'undefined' ? 'undefined' : _typeof(p)) !== 'object' || Object.isFrozen(p)) continue; | ||
if (!p || !hasOwnProp.call(o, k) || _typeof(p) !== 'object' || Object.isFrozen(p)) continue; | ||
deepFreeze(p); | ||
@@ -387,5 +369,4 @@ } | ||
deepFreeze = freezer.bind(null, true); | ||
exports.deepFreeze = deepFreeze; | ||
exports.freeze = freeze; | ||
exports.deepFreeze = deepFreeze; | ||
@@ -406,15 +387,16 @@ /** | ||
*/ | ||
var NOT_FOUND_OBJECT = { | ||
data: undefined, | ||
solvedPath: null, | ||
exists: false | ||
}; | ||
var NOT_FOUND_OBJECT = { data: undefined, solvedPath: null, exists: false }; | ||
function getIn(object, path) { | ||
if (!path) return NOT_FOUND_OBJECT; | ||
var solvedPath = []; | ||
var exists = true, | ||
c = object, | ||
idx = void 0, | ||
i = void 0, | ||
l = void 0; | ||
idx, | ||
i, | ||
l; | ||
@@ -429,12 +411,9 @@ for (i = 0, l = path.length; i < l; i++) { | ||
if (typeof path[i] === 'function') { | ||
if (!_type2.default.array(c)) return NOT_FOUND_OBJECT; | ||
if (!_type["default"].array(c)) return NOT_FOUND_OBJECT; | ||
idx = index(c, path[i]); | ||
if (!~idx) return NOT_FOUND_OBJECT; | ||
solvedPath.push(idx); | ||
c = c[idx]; | ||
} else if (_typeof(path[i]) === 'object') { | ||
if (!_type2.default.array(c)) return NOT_FOUND_OBJECT; | ||
if (!_type["default"].array(c)) return NOT_FOUND_OBJECT; | ||
idx = index(c, function (e) { | ||
@@ -444,3 +423,2 @@ return compare(e, path[i]); | ||
if (!~idx) return NOT_FOUND_OBJECT; | ||
solvedPath.push(idx); | ||
@@ -450,3 +428,3 @@ c = c[idx]; | ||
solvedPath.push(path[i]); | ||
exists = (typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object' && path[i] in c; | ||
exists = _typeof(c) === 'object' && path[i] in c; | ||
c = c[path[i]]; | ||
@@ -456,5 +434,8 @@ } | ||
return { data: c, solvedPath: solvedPath, exists: exists }; | ||
return { | ||
data: c, | ||
solvedPath: solvedPath, | ||
exists: exists | ||
}; | ||
} | ||
/** | ||
@@ -467,2 +448,4 @@ * Little helper returning a JavaScript error carrying some data with it. | ||
*/ | ||
function makeError(message, data) { | ||
@@ -473,5 +456,6 @@ var err = new Error(message); | ||
err[k] = data[k]; | ||
}return err; | ||
} | ||
return err; | ||
} | ||
/** | ||
@@ -487,4 +471,6 @@ * Function taking n objects to merge them together. | ||
*/ | ||
function merger(deep) { | ||
for (var _len = arguments.length, objects = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
objects[_key - 1] = arguments[_key]; | ||
@@ -494,8 +480,4 @@ } | ||
var o = objects[0]; | ||
var t, i, l, k; | ||
var t = void 0, | ||
i = void 0, | ||
l = void 0, | ||
k = void 0; | ||
for (i = 1, l = objects.length; i < l; i++) { | ||
@@ -505,3 +487,3 @@ t = objects[i]; | ||
for (k in t) { | ||
if (deep && _type2.default.object(t[k]) && !(t[k] instanceof _monkey.Monkey)) { | ||
if (deep && _type["default"].object(t[k]) && !(t[k] instanceof _monkey.Monkey)) { | ||
o[k] = merger(true, o[k] || {}, t[k]); | ||
@@ -516,11 +498,11 @@ } else { | ||
} | ||
/** | ||
* Exporting both `shallowMerge` and `deepMerge` functions. | ||
*/ | ||
var shallowMerge = merger.bind(null, false), | ||
deepMerge = merger.bind(null, true); | ||
exports.deepMerge = deepMerge; | ||
exports.shallowMerge = shallowMerge; | ||
exports.deepMerge = deepMerge; | ||
@@ -534,11 +516,8 @@ /** | ||
*/ | ||
function hashPath(path) { | ||
return 'λ' + path.map(function (step) { | ||
if (_type2.default.function(step) || _type2.default.object(step)) return '#' + uniqid() + '#'; | ||
if (_type["default"]["function"](step) || _type["default"].object(step)) return "#".concat(uniqid(), "#"); | ||
return step; | ||
}).join('λ'); | ||
} | ||
/** | ||
@@ -551,6 +530,7 @@ * Solving a potentially relative path. | ||
*/ | ||
function solveRelativePath(base, to) { | ||
var solvedPath = []; | ||
var solvedPath = []; // Coercing to array | ||
// Coercing to array | ||
to = [].concat(to); | ||
@@ -572,3 +552,2 @@ | ||
} | ||
/** | ||
@@ -592,34 +571,21 @@ * Function determining whether some paths in the tree were affected by some | ||
*/ | ||
function solveUpdate(affectedPaths, comparedPaths) { | ||
var i = void 0, | ||
j = void 0, | ||
k = void 0, | ||
l = void 0, | ||
m = void 0, | ||
n = void 0, | ||
p = void 0, | ||
c = void 0, | ||
s = void 0; | ||
var i, j, k, l, m, n, p, c, s; // Looping through possible paths | ||
// Looping through possible paths | ||
for (i = 0, l = affectedPaths.length; i < l; i++) { | ||
p = affectedPaths[i]; | ||
if (!p.length) return true; // Looping through logged paths | ||
if (!p.length) return true; | ||
// Looping through logged paths | ||
for (j = 0, m = comparedPaths.length; j < m; j++) { | ||
c = comparedPaths[j]; | ||
if (!c || !c.length) return true; // Looping through steps | ||
if (!c || !c.length) return true; | ||
// Looping through steps | ||
for (k = 0, n = c.length; k < n; k++) { | ||
s = c[k]; | ||
// If path is not relevant, we break | ||
s = c[k]; // If path is not relevant, we break | ||
// NOTE: the '!=' instead of '!==' is required here! | ||
if (s != p[k]) break; | ||
// If we reached last item and we are relevant | ||
if (s != p[k]) break; // If we reached last item and we are relevant | ||
if (k + 1 === n || k + 1 === p.length) return true; | ||
@@ -632,3 +598,2 @@ } | ||
} | ||
/** | ||
@@ -643,23 +608,21 @@ * Non-mutative version of the splice array method. | ||
*/ | ||
function splice(array, startIndex, nb) { | ||
for (var _len2 = arguments.length, elements = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) { | ||
for (var _len2 = arguments.length, elements = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) { | ||
elements[_key2 - 3] = arguments[_key2]; | ||
} | ||
if (nb === undefined && arguments.length === 2) nb = array.length - startIndex;else if (nb === null || nb === undefined) nb = 0;else if (isNaN(+nb)) throw new Error('argument nb ' + nb + ' can not be parsed into a number!'); | ||
nb = Math.max(0, nb); | ||
if (nb === undefined && arguments.length === 2) nb = array.length - startIndex;else if (nb === null || nb === undefined) nb = 0;else if (isNaN(+nb)) throw new Error("argument nb ".concat(nb, " can not be parsed into a number!")); | ||
nb = Math.max(0, nb); // Solving startIndex | ||
// Solving startIndex | ||
if (_type2.default.function(startIndex)) startIndex = index(array, startIndex); | ||
if (_type2.default.object(startIndex)) startIndex = index(array, function (e) { | ||
if (_type["default"]["function"](startIndex)) startIndex = index(array, startIndex); | ||
if (_type["default"].object(startIndex)) startIndex = index(array, function (e) { | ||
return compare(e, startIndex); | ||
}); | ||
}); // Positive index | ||
// Positive index | ||
if (startIndex >= 0) return array.slice(0, startIndex).concat(elements).concat(array.slice(startIndex + nb)); | ||
if (startIndex >= 0) return array.slice(0, startIndex).concat(elements).concat(array.slice(startIndex + nb)); // Negative index | ||
// Negative index | ||
return array.slice(0, array.length + startIndex).concat(elements).concat(array.slice(array.length + startIndex + nb)); | ||
} | ||
/** | ||
@@ -670,5 +633,6 @@ * Function returning a unique incremental id each time it is called. | ||
*/ | ||
var uniqid = function () { | ||
var i = 0; | ||
return function () { | ||
@@ -675,0 +639,0 @@ return i++; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,26 +6,18 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.Monkey = exports.MonkeyDefinition = undefined; | ||
exports.Monkey = exports.MonkeyDefinition = void 0; | ||
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 _type = _interopRequireDefault(require("./type")); | ||
var _type = require('./type'); | ||
var _update2 = _interopRequireDefault(require("./update")); | ||
var _type2 = _interopRequireDefault(_type); | ||
var _helpers = require("./helpers"); | ||
var _update2 = require('./update'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _update3 = _interopRequireDefault(_update2); | ||
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); } } | ||
var _helpers = require('./helpers'); | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** | ||
* Baobab Monkeys | ||
* =============== | ||
* | ||
* Exposing both handy monkey definitions and the underlying working class. | ||
*/ | ||
/** | ||
@@ -39,3 +31,3 @@ * Monkey Definition class | ||
*/ | ||
var MonkeyDefinition = exports.MonkeyDefinition = function MonkeyDefinition(definition) { | ||
var MonkeyDefinition = function MonkeyDefinition(definition) { | ||
var _this = this; | ||
@@ -45,6 +37,7 @@ | ||
var monkeyType = _type2.default.monkeyDefinition(definition); | ||
var monkeyType = _type["default"].monkeyDefinition(definition); | ||
if (!monkeyType) throw (0, _helpers.makeError)('Baobab.monkey: invalid definition.', { definition: definition }); | ||
if (!monkeyType) throw (0, _helpers.makeError)('Baobab.monkey: invalid definition.', { | ||
definition: definition | ||
}); | ||
this.type = monkeyType; | ||
@@ -63,3 +56,3 @@ | ||
if (_type2.default.object(definition[definition.length - 1])) { | ||
if (_type["default"].object(definition[definition.length - 1])) { | ||
offset++; | ||
@@ -73,13 +66,11 @@ options = definition[definition.length - 1]; | ||
this.options = options; | ||
} | ||
} // Coercing paths for convenience | ||
// Coercing paths for convenience | ||
this.paths = this.paths.map(function (p) { | ||
return [].concat(p); | ||
}); | ||
}); // Does the definition contain dynamic paths | ||
// Does the definition contain dynamic paths | ||
this.hasDynamicPaths = this.paths.some(_type2.default.dynamicPath); | ||
this.hasDynamicPaths = this.paths.some(_type["default"].dynamicPath); | ||
}; | ||
/** | ||
@@ -94,3 +85,7 @@ * Monkey core class | ||
var Monkey = exports.Monkey = function () { | ||
exports.MonkeyDefinition = MonkeyDefinition; | ||
var Monkey = | ||
/*#__PURE__*/ | ||
function () { | ||
function Monkey(tree, pathInTree, definition) { | ||
@@ -104,5 +99,4 @@ var _this2 = this; | ||
this.path = pathInTree; | ||
this.definition = definition; | ||
this.definition = definition; // Adapting the definition's paths & projection to this monkey's case | ||
// Adapting the definition's paths & projection to this monkey's case | ||
var projection = definition.projection, | ||
@@ -122,9 +116,8 @@ relative = _helpers.solveRelativePath.bind(null, pathInTree.slice(0, -1)); | ||
this.depPaths = this.projection; | ||
} | ||
} // Internal state | ||
// Internal state | ||
this.state = { | ||
killed: false | ||
}; | ||
/** | ||
@@ -137,13 +130,10 @@ * Listener on the tree's `write` event. | ||
*/ | ||
this.writeListener = function (_ref) { | ||
var path = _ref.data.path; | ||
if (_this2.state.killed) return; // Is the monkey affected by the current write event? | ||
if (_this2.state.killed) return; | ||
// Is the monkey affected by the current write event? | ||
var concerned = (0, _helpers.solveUpdate)([path], _this2.relatedPaths()); | ||
if (concerned) _this2.update(); | ||
}; | ||
/** | ||
@@ -156,2 +146,4 @@ * Listener on the tree's `monkey` event. | ||
*/ | ||
this.recursiveListener = function (_ref2) { | ||
@@ -161,22 +153,16 @@ var _ref2$data = _ref2.data, | ||
path = _ref2$data.path; | ||
if (_this2.state.killed) return; // Breaking if this is the same monkey | ||
if (_this2.state.killed) return; | ||
if (_this2 === monkey) return; // Is the monkey affected by the current monkey event? | ||
// Breaking if this is the same monkey | ||
if (_this2 === monkey) return; | ||
// Is the monkey affected by the current monkey event? | ||
var concerned = (0, _helpers.solveUpdate)([path], _this2.relatedPaths(false)); | ||
if (concerned) _this2.update(); | ||
}; | ||
}; // Binding listeners | ||
// Binding listeners | ||
this.tree.on('write', this.writeListener); | ||
this.tree.on('_monkey', this.recursiveListener); | ||
this.tree.on('_monkey', this.recursiveListener); // Updating relevant node | ||
// Updating relevant node | ||
this.update(); | ||
} | ||
/** | ||
@@ -191,3 +177,3 @@ * Method returning solved paths related to the monkey. | ||
_createClass(Monkey, [{ | ||
key: 'relatedPaths', | ||
key: "relatedPaths", | ||
value: function relatedPaths() { | ||
@@ -197,27 +183,19 @@ var _this3 = this; | ||
var recursive = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; | ||
var paths = void 0; | ||
var paths; | ||
if (this.definition.hasDynamicPaths) paths = this.depPaths.map(function (p) { | ||
return (0, _helpers.getIn)(_this3.tree._data, p).solvedPath; | ||
});else paths = this.depPaths; | ||
var isRecursive = recursive && this.depPaths.some(function (p) { | ||
return !!_type2.default.monkeyPath(_this3.tree._monkeys, p); | ||
return !!_type["default"].monkeyPath(_this3.tree._monkeys, p); | ||
}); | ||
if (!isRecursive) return paths; | ||
return paths.reduce(function (accumulatedPaths, path) { | ||
var monkeyPath = _type2.default.monkeyPath(_this3.tree._monkeys, path); | ||
var monkeyPath = _type["default"].monkeyPath(_this3.tree._monkeys, path); | ||
if (!monkeyPath) return accumulatedPaths.concat([path]); | ||
if (!monkeyPath) return accumulatedPaths.concat([path]); // Solving recursive path | ||
// Solving recursive path | ||
var relatedMonkey = (0, _helpers.getIn)(_this3.tree._monkeys, monkeyPath).data; | ||
return accumulatedPaths.concat(relatedMonkey.relatedPaths()); | ||
}, []); | ||
} | ||
/** | ||
@@ -231,3 +209,3 @@ * Method used to update the tree's internal data with a lazy getter holding | ||
}, { | ||
key: 'update', | ||
key: "update", | ||
value: function update() { | ||
@@ -241,14 +219,9 @@ var _this4 = this; | ||
alreadyComputed = false; | ||
return function () { | ||
if (!alreadyComputed) { | ||
cache = def.getter.apply(tree, def.type === 'object' ? [data] : data); | ||
if (tree.options.immutable && def.options.immutable !== false) (0, _helpers.deepFreeze)(cache); // update tree affected paths | ||
if (tree.options.immutable && def.options.immutable !== false) (0, _helpers.deepFreeze)(cache); | ||
// update tree affected paths | ||
var hash = (0, _helpers.hashPath)(_this4.path); | ||
tree._affectedPathsIndex[hash] = true; | ||
alreadyComputed = true; | ||
@@ -261,7 +234,6 @@ } | ||
lazyGetter.isLazyGetter = true; | ||
lazyGetter.isLazyGetter = true; // Should we write the lazy getter in the tree or solve it right now? | ||
// Should we write the lazy getter in the tree or solve it right now? | ||
if (this.tree.options.lazyMonkeys) { | ||
this.tree._data = (0, _update3.default)(this.tree._data, this.path, { | ||
this.tree._data = (0, _update2["default"])(this.tree._data, this.path, { | ||
type: 'monkey', | ||
@@ -271,3 +243,3 @@ value: lazyGetter | ||
} else { | ||
var result = (0, _update3.default)(this.tree._data, this.path, { | ||
var result = (0, _update2["default"])(this.tree._data, this.path, { | ||
type: 'set', | ||
@@ -279,12 +251,12 @@ value: lazyGetter(), | ||
}, this.tree.options); | ||
if ('data' in result) this.tree._data = result.data; | ||
} | ||
} // Notifying the monkey's update so we can handle recursivity | ||
// Notifying the monkey's update so we can handle recursivity | ||
this.tree.emit('_monkey', { monkey: this, path: this.path }); | ||
this.tree.emit('_monkey', { | ||
monkey: this, | ||
path: this.path | ||
}); | ||
return this; | ||
} | ||
/** | ||
@@ -295,13 +267,11 @@ * Method releasing the monkey from memory. | ||
}, { | ||
key: 'release', | ||
key: "release", | ||
value: function release() { | ||
// Unbinding events | ||
this.tree.off('write', this.writeListener); | ||
this.tree.off('_monkey', this.recursiveListener); | ||
this.state.killed = true; | ||
// Deleting properties | ||
this.state.killed = true; // Deleting properties | ||
// NOTE: not deleting this.definition because some strange things happen | ||
// in the _refreshMonkeys method. See #372. | ||
delete this.projection; | ||
@@ -314,2 +284,4 @@ delete this.depPaths; | ||
return Monkey; | ||
}(); | ||
}(); | ||
exports.Monkey = Monkey; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,17 +6,9 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports["default"] = void 0; | ||
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; }; /** | ||
* Baobab Type Checking | ||
* ===================== | ||
* | ||
* Helpers functions used throughout the library to perform some type | ||
* tests at runtime. | ||
* | ||
*/ | ||
var _monkey = require("./monkey"); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _monkey = require('./monkey'); | ||
var type = {}; | ||
/** | ||
@@ -36,2 +28,3 @@ * Helpers | ||
*/ | ||
function anyOf(target, allowed) { | ||
@@ -42,3 +35,2 @@ return allowed.some(function (t) { | ||
} | ||
/** | ||
@@ -55,6 +47,7 @@ * Simple types | ||
*/ | ||
type.array = function (target) { | ||
return Array.isArray(target); | ||
}; | ||
/** | ||
@@ -66,6 +59,7 @@ * Checking whether the given variable is an object. | ||
*/ | ||
type.object = function (target) { | ||
return target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && !Array.isArray(target) && !(target instanceof Date) && !(target instanceof RegExp) && !(typeof Map === 'function' && target instanceof Map) && !(typeof Set === 'function' && target instanceof Set); | ||
return target && _typeof(target) === 'object' && !Array.isArray(target) && !(target instanceof Date) && !(target instanceof RegExp) && !(typeof Map === 'function' && target instanceof Map) && !(typeof Set === 'function' && target instanceof Set); | ||
}; | ||
/** | ||
@@ -77,6 +71,7 @@ * Checking whether the given variable is a string. | ||
*/ | ||
type.string = function (target) { | ||
return typeof target === 'string'; | ||
}; | ||
/** | ||
@@ -88,6 +83,7 @@ * Checking whether the given variable is a number. | ||
*/ | ||
type.number = function (target) { | ||
return typeof target === 'number'; | ||
}; | ||
/** | ||
@@ -99,6 +95,7 @@ * Checking whether the given variable is a function. | ||
*/ | ||
type.function = function (target) { | ||
type["function"] = function (target) { | ||
return typeof target === 'function'; | ||
}; | ||
/** | ||
@@ -110,6 +107,7 @@ * Checking whether the given variable is a JavaScript primitive. | ||
*/ | ||
type.primitive = function (target) { | ||
return target !== Object(target); | ||
}; | ||
/** | ||
@@ -127,9 +125,9 @@ * Complex types | ||
*/ | ||
type.splicer = function (target) { | ||
if (!type.array(target) || target.length < 1) return false; | ||
if (target.length > 1 && isNaN(+target[1])) return false; | ||
return anyOf(target[0], ['number', 'function', 'object']); | ||
}; | ||
/** | ||
@@ -142,4 +140,5 @@ * Checking whether the given variable is a valid cursor path. | ||
*/ | ||
// Order is important for performance reasons | ||
// Order is important for performance reasons | ||
var ALLOWED_FOR_PATH = ['string', 'number', 'function', 'object']; | ||
@@ -149,3 +148,2 @@ | ||
if (!target && target !== 0 && target !== '') return false; | ||
return [].concat(target).every(function (step) { | ||
@@ -155,3 +153,2 @@ return anyOf(step, ALLOWED_FOR_PATH); | ||
}; | ||
/** | ||
@@ -163,8 +160,9 @@ * Checking whether the given path is a dynamic one. | ||
*/ | ||
type.dynamicPath = function (path) { | ||
return path.some(function (step) { | ||
return type.function(step) || type.object(step); | ||
return type["function"](step) || type.object(step); | ||
}); | ||
}; | ||
/** | ||
@@ -178,16 +176,14 @@ * Retrieve any monkey subpath in the given path or null if the path never comes | ||
*/ | ||
type.monkeyPath = function (data, path) { | ||
var subpath = []; | ||
var c = data, | ||
i = void 0, | ||
l = void 0; | ||
i, | ||
l; | ||
for (i = 0, l = path.length; i < l; i++) { | ||
subpath.push(path[i]); | ||
if ((typeof c === 'undefined' ? 'undefined' : _typeof(c)) !== 'object') return null; | ||
if (_typeof(c) !== 'object') return null; | ||
c = c[path[i]]; | ||
if (c instanceof _monkey.Monkey) return subpath; | ||
@@ -198,3 +194,2 @@ } | ||
}; | ||
/** | ||
@@ -207,8 +202,8 @@ * Check if the given object property is a lazy getter used by a monkey. | ||
*/ | ||
type.lazyGetter = function (o, propertyKey) { | ||
var descriptor = Object.getOwnPropertyDescriptor(o, propertyKey); | ||
return descriptor && descriptor.get && descriptor.get.isLazyGetter === true; | ||
}; | ||
/** | ||
@@ -220,19 +215,16 @@ * Returns the type of the given monkey definition or `null` if invalid. | ||
*/ | ||
type.monkeyDefinition = function (definition) { | ||
if (type.object(definition)) { | ||
if (!type.function(definition.get) || definition.cursors && (!type.object(definition.cursors) || !Object.keys(definition.cursors).every(function (k) { | ||
if (!type["function"](definition.get) || definition.cursors && (!type.object(definition.cursors) || !Object.keys(definition.cursors).every(function (k) { | ||
return type.path(definition.cursors[k]); | ||
}))) return null; | ||
return 'object'; | ||
} else if (type.array(definition)) { | ||
var offset = 1; | ||
if (type.object(definition[definition.length - 1])) offset++; | ||
if (!type.function(definition[definition.length - offset]) || !definition.slice(0, -offset).every(function (p) { | ||
if (!type["function"](definition[definition.length - offset]) || !definition.slice(0, -offset).every(function (p) { | ||
return type.path(p); | ||
})) return null; | ||
return 'array'; | ||
@@ -243,3 +235,2 @@ } | ||
}; | ||
/** | ||
@@ -251,2 +242,4 @@ * Checking whether the given watcher definition is valid. | ||
*/ | ||
type.watcherMapping = function (definition) { | ||
@@ -257,3 +250,2 @@ return type.object(definition) && Object.keys(definition).every(function (k) { | ||
}; | ||
/** | ||
@@ -265,4 +257,5 @@ * Checking whether the given string is a valid operation type. | ||
*/ | ||
// Ordered by likeliness | ||
// Ordered by likeliness | ||
var VALID_OPERATIONS = ['set', 'apply', 'push', 'unshift', 'concat', 'pop', 'shift', 'deepMerge', 'merge', 'splice', 'unset']; | ||
@@ -274,2 +267,3 @@ | ||
exports.default = type; | ||
var _default = type; | ||
exports["default"] = _default; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,24 +6,23 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = update; | ||
exports["default"] = update; | ||
var _type = require('./type'); | ||
var _type = _interopRequireDefault(require("./type")); | ||
var _type2 = _interopRequireDefault(_type); | ||
var _helpers = require("./helpers"); | ||
var _helpers = require('./helpers'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } /** | ||
* Baobab Update | ||
* ============== | ||
* | ||
* The tree's update scheme. | ||
*/ | ||
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } | ||
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } | ||
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } | ||
function err(operation, expectedTarget, path) { | ||
return (0, _helpers.makeError)('Baobab.update: cannot apply the "' + operation + '" on ' + ('a non ' + expectedTarget + ' (path: /' + path.join('/') + ').'), { path: path }); | ||
return (0, _helpers.makeError)("Baobab.update: cannot apply the \"".concat(operation, "\" on ") + "a non ".concat(expectedTarget, " (path: /").concat(path.join('/'), ")."), { | ||
path: path | ||
}); | ||
} | ||
/** | ||
@@ -39,2 +38,4 @@ * Function aiming at applying a single update operation on the given tree's | ||
*/ | ||
function update(data, path, operation) { | ||
@@ -45,29 +46,24 @@ var opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
_operation$options = operation.options, | ||
operationOptions = _operation$options === undefined ? {} : _operation$options; | ||
operationOptions = _operation$options === void 0 ? {} : _operation$options; // Dummy root, so we can shift and alter the root | ||
// Dummy root, so we can shift and alter the root | ||
var dummy = { root: data }, | ||
var dummy = { | ||
root: data | ||
}, | ||
dummyPath = ['root'].concat(_toConsumableArray(path)), | ||
currentPath = []; | ||
currentPath = []; // Walking the path | ||
// Walking the path | ||
var p = dummy, | ||
i = void 0, | ||
l = void 0, | ||
s = void 0; | ||
i, | ||
l, | ||
s; | ||
for (i = 0, l = dummyPath.length; i < l; i++) { | ||
// Current item's reference is therefore p[s] | ||
// The reason why we don't create a variable here for convenience | ||
// is because we actually need to mutate the reference. | ||
s = dummyPath[i]; | ||
s = dummyPath[i]; // Updating the path | ||
// Updating the path | ||
if (i > 0) currentPath.push(s); | ||
if (i > 0) currentPath.push(s); // If we reached the end of the path, we apply the operation | ||
// If we reached the end of the path, we apply the operation | ||
if (i === l - 1) { | ||
/** | ||
@@ -77,7 +73,8 @@ * Set | ||
if (operationType === 'set') { | ||
// Purity check | ||
if (opts.pure && p[s] === value) return { node: p[s] }; | ||
if (opts.pure && p[s] === value) return { | ||
node: p[s] | ||
}; | ||
if (_type2.default.lazyGetter(p, s)) { | ||
if (_type["default"].lazyGetter(p, s)) { | ||
Object.defineProperty(p, s, { | ||
@@ -94,3 +91,2 @@ value: value, | ||
} | ||
/** | ||
@@ -106,3 +102,2 @@ * Monkey | ||
} | ||
/** | ||
@@ -112,8 +107,9 @@ * Apply | ||
else if (operationType === 'apply') { | ||
var result = value(p[s]); | ||
var result = value(p[s]); // Purity check | ||
// Purity check | ||
if (opts.pure && p[s] === result) return { node: p[s] }; | ||
if (opts.pure && p[s] === result) return { | ||
node: p[s] | ||
}; | ||
if (_type2.default.lazyGetter(p, s)) { | ||
if (_type["default"].lazyGetter(p, s)) { | ||
Object.defineProperty(p, s, { | ||
@@ -130,3 +126,2 @@ value: result, | ||
} | ||
/** | ||
@@ -136,7 +131,5 @@ * Push | ||
else if (operationType === 'push') { | ||
if (!_type2.default.array(p[s])) throw err('push', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('push', 'array', currentPath); | ||
if (opts.persistent) p[s] = p[s].concat([value]);else p[s].push(value); | ||
} | ||
/** | ||
@@ -146,7 +139,5 @@ * Unshift | ||
else if (operationType === 'unshift') { | ||
if (!_type2.default.array(p[s])) throw err('unshift', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('unshift', 'array', currentPath); | ||
if (opts.persistent) p[s] = [value].concat(p[s]);else p[s].unshift(value); | ||
} | ||
/** | ||
@@ -156,7 +147,5 @@ * Concat | ||
else if (operationType === 'concat') { | ||
if (!_type2.default.array(p[s])) throw err('concat', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('concat', 'array', currentPath); | ||
if (opts.persistent) p[s] = p[s].concat(value);else p[s].push.apply(p[s], value); | ||
} | ||
/** | ||
@@ -166,7 +155,5 @@ * Splice | ||
else if (operationType === 'splice') { | ||
if (!_type2.default.array(p[s])) throw err('splice', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('splice', 'array', currentPath); | ||
if (opts.persistent) p[s] = _helpers.splice.apply(null, [p[s]].concat(value));else p[s].splice.apply(p[s], value); | ||
} | ||
/** | ||
@@ -176,7 +163,5 @@ * Pop | ||
else if (operationType === 'pop') { | ||
if (!_type2.default.array(p[s])) throw err('pop', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('pop', 'array', currentPath); | ||
if (opts.persistent) p[s] = (0, _helpers.splice)(p[s], -1, 1);else p[s].pop(); | ||
} | ||
/** | ||
@@ -186,7 +171,5 @@ * Shift | ||
else if (operationType === 'shift') { | ||
if (!_type2.default.array(p[s])) throw err('shift', 'array', currentPath); | ||
if (!_type["default"].array(p[s])) throw err('shift', 'array', currentPath); | ||
if (opts.persistent) p[s] = (0, _helpers.splice)(p[s], 0, 1);else p[s].shift(); | ||
} | ||
/** | ||
@@ -196,5 +179,4 @@ * Unset | ||
else if (operationType === 'unset') { | ||
if (_type2.default.object(p)) delete p[s];else if (_type2.default.array(p)) p.splice(s, 1); | ||
if (_type["default"].object(p)) delete p[s];else if (_type["default"].array(p)) p.splice(s, 1); | ||
} | ||
/** | ||
@@ -204,7 +186,5 @@ * Merge | ||
else if (operationType === 'merge') { | ||
if (!_type2.default.object(p[s])) throw err('merge', 'object', currentPath); | ||
if (!_type["default"].object(p[s])) throw err('merge', 'object', currentPath); | ||
if (opts.persistent) p[s] = (0, _helpers.shallowMerge)({}, p[s], value);else p[s] = (0, _helpers.shallowMerge)(p[s], value); | ||
} | ||
/** | ||
@@ -214,34 +194,31 @@ * Deep merge | ||
else if (operationType === 'deepMerge') { | ||
if (!_type2.default.object(p[s])) throw err('deepMerge', 'object', currentPath); | ||
if (!_type["default"].object(p[s])) throw err('deepMerge', 'object', currentPath); | ||
if (opts.persistent) p[s] = (0, _helpers.deepMerge)({}, p[s], value);else p[s] = (0, _helpers.deepMerge)(p[s], value); | ||
} | ||
} // Deep freezing the resulting value | ||
// Deep freezing the resulting value | ||
if (opts.immutable && !operationOptions.mutableLeaf) (0, _helpers.deepFreeze)(p); | ||
break; | ||
} | ||
// If we reached a leaf, we override by setting an empty object | ||
else if (_type2.default.primitive(p[s])) { | ||
} // If we reached a leaf, we override by setting an empty object | ||
else if (_type["default"].primitive(p[s])) { | ||
p[s] = {}; | ||
} | ||
// Else, we shift the reference and continue the path | ||
} // Else, we shift the reference and continue the path | ||
else if (opts.persistent) { | ||
p[s] = (0, _helpers.shallowClone)(p[s]); | ||
} | ||
} // Should we freeze the current step before continuing? | ||
// Should we freeze the current step before continuing? | ||
if (opts.immutable && l > 0) (0, _helpers.freeze)(p); | ||
p = p[s]; | ||
} | ||
} // If we are updating a dynamic node, we need not return the affected node | ||
// If we are updating a dynamic node, we need not return the affected node | ||
if (_type2.default.lazyGetter(p, s)) return { data: dummy.root }; | ||
// Returning new data object | ||
return { data: dummy.root, node: p[s] }; | ||
if (_type["default"].lazyGetter(p, s)) return { | ||
data: dummy.root | ||
}; // Returning new data object | ||
return { | ||
data: dummy.root, | ||
node: p[s] | ||
}; | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,34 +6,32 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports["default"] = void 0; | ||
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 _emmett = _interopRequireDefault(require("emmett")); | ||
var _emmett = require('emmett'); | ||
var _cursor = _interopRequireDefault(require("./cursor")); | ||
var _emmett2 = _interopRequireDefault(_emmett); | ||
var _type = _interopRequireDefault(require("./type")); | ||
var _cursor = require('./cursor'); | ||
var _helpers = require("./helpers"); | ||
var _cursor2 = _interopRequireDefault(_cursor); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _type = require('./type'); | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
var _type2 = _interopRequireDefault(_type); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _helpers = require('./helpers'); | ||
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); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** | ||
* Baobab Watchers | ||
* ================ | ||
* | ||
* Abstraction used to listen and retrieve data from multiple parts of a | ||
* Baobab tree at once. | ||
*/ | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
/** | ||
@@ -46,22 +44,23 @@ * Watcher class. | ||
*/ | ||
var Watcher = function (_Emitter) { | ||
var Watcher = | ||
/*#__PURE__*/ | ||
function (_Emitter) { | ||
_inherits(Watcher, _Emitter); | ||
function Watcher(tree, mapping) { | ||
var _this; | ||
_classCallCheck(this, Watcher); | ||
// Properties | ||
var _this = _possibleConstructorReturn(this, (Watcher.__proto__ || Object.getPrototypeOf(Watcher)).call(this)); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Watcher).call(this)); // Properties | ||
_this.tree = tree; | ||
_this.mapping = null; | ||
_this.state = { | ||
killed: false | ||
}; | ||
}; // Initializing | ||
// Initializing | ||
_this.refresh(mapping); | ||
_this.refresh(mapping); // Listening | ||
// Listening | ||
_this.handler = function (e) { | ||
@@ -76,5 +75,5 @@ if (_this.state.killed) return; | ||
_this.tree.on('update', _this.handler); | ||
return _this; | ||
} | ||
/** | ||
@@ -88,3 +87,3 @@ * Method used to get the current watched paths. | ||
_createClass(Watcher, [{ | ||
key: 'getWatchedPaths', | ||
key: "getWatchedPaths", | ||
value: function getWatchedPaths() { | ||
@@ -94,29 +93,20 @@ var _this2 = this; | ||
var rawPaths = Object.keys(this.mapping).map(function (k) { | ||
var v = _this2.mapping[k]; | ||
var v = _this2.mapping[k]; // Watcher mappings can accept a cursor | ||
// Watcher mappings can accept a cursor | ||
if (v instanceof _cursor2.default) return v.solvedPath; | ||
if (v instanceof _cursor["default"]) return v.solvedPath; | ||
return _this2.mapping[k]; | ||
}); | ||
return rawPaths.reduce(function (cp, p) { | ||
// Handling path polymorphisms | ||
p = [].concat(p); | ||
p = [].concat(p); // Dynamic path? | ||
// Dynamic path? | ||
if (_type2.default.dynamicPath(p)) p = (0, _helpers.getIn)(_this2.tree._data, p).solvedPath; | ||
if (_type["default"].dynamicPath(p)) p = (0, _helpers.getIn)(_this2.tree._data, p).solvedPath; | ||
if (!p) return cp; // Facet path? | ||
if (!p) return cp; | ||
var monkeyPath = _type["default"].monkeyPath(_this2.tree._monkeys, p); | ||
// Facet path? | ||
var monkeyPath = _type2.default.monkeyPath(_this2.tree._monkeys, p); | ||
if (monkeyPath) return cp.concat((0, _helpers.getIn)(_this2.tree._monkeys, monkeyPath).data.relatedPaths()); | ||
return cp.concat([p]); | ||
}, []); | ||
} | ||
/** | ||
@@ -129,3 +119,3 @@ * Method used to return a map of the watcher's cursors. | ||
}, { | ||
key: 'getCursors', | ||
key: "getCursors", | ||
value: function getCursors() { | ||
@@ -135,12 +125,8 @@ var _this3 = this; | ||
var cursors = {}; | ||
Object.keys(this.mapping).forEach(function (k) { | ||
var path = _this3.mapping[k]; | ||
if (path instanceof _cursor2.default) cursors[k] = path;else cursors[k] = _this3.tree.select(path); | ||
if (path instanceof _cursor["default"]) cursors[k] = path;else cursors[k] = _this3.tree.select(path); | ||
}); | ||
return cursors; | ||
} | ||
/** | ||
@@ -154,17 +140,17 @@ * Method used to refresh the watcher's mapping. | ||
}, { | ||
key: 'refresh', | ||
key: "refresh", | ||
value: function refresh(mapping) { | ||
if (!_type["default"].watcherMapping(mapping)) throw (0, _helpers.makeError)('Baobab.watch: invalid mapping.', { | ||
mapping: mapping | ||
}); | ||
this.mapping = mapping; // Creating the get method | ||
if (!_type2.default.watcherMapping(mapping)) throw (0, _helpers.makeError)('Baobab.watch: invalid mapping.', { mapping: mapping }); | ||
this.mapping = mapping; | ||
// Creating the get method | ||
var projection = {}; | ||
for (var k in mapping) { | ||
projection[k] = mapping[k] instanceof _cursor2.default ? mapping[k].path : mapping[k]; | ||
}this.get = this.tree.project.bind(this.tree, projection); | ||
projection[k] = mapping[k] instanceof _cursor["default"] ? mapping[k].path : mapping[k]; | ||
} | ||
this.get = this.tree.project.bind(this.tree, projection); | ||
} | ||
/** | ||
@@ -175,5 +161,4 @@ * Methods releasing the watcher from memory. | ||
}, { | ||
key: 'release', | ||
key: "release", | ||
value: function release() { | ||
this.tree.off('update', this.handler); | ||
@@ -186,4 +171,4 @@ this.state.killed = true; | ||
return Watcher; | ||
}(_emmett2.default); | ||
}(_emmett["default"]); | ||
exports.default = Watcher; | ||
exports["default"] = Watcher; |
{ | ||
"name": "baobab", | ||
"version": "2.5.2", | ||
"version": "2.5.3", | ||
"description": "JavaScript persistent data tree with cursors.", | ||
@@ -10,25 +10,27 @@ "main": "./dist/baobab.js", | ||
"devDependencies": { | ||
"@babel/cli": "^7.7.4", | ||
"@babel/core": "^7.7.4", | ||
"@babel/node": "^7.7.4", | ||
"@babel/preset-env": "7.7.4", | ||
"@babel/register": "^7.7.4", | ||
"@yomguithereal/eslint-config": "^4.0.0", | ||
"add-banner": "^0.1.0", | ||
"async": "^2.5.0", | ||
"babel-cli": "^6.26.0", | ||
"babel-core": "^6.26.0", | ||
"babel-preset-es2015": "^6.24.1", | ||
"babelify": "^8.0.0", | ||
"async": "^3.1.0", | ||
"babelify": "^10.0.0", | ||
"benchmark": "^2.1.4", | ||
"browserify": "^14.5.0", | ||
"eslint": "^4.10.0", | ||
"browserify": "^16.5.0", | ||
"eslint": "^6.7.2", | ||
"fs-extra": "^8.1.0", | ||
"lodash": "^4.17.4", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^4.0.1", | ||
"uglify-js": "^3.1.6" | ||
"mocha": "^6.2.2", | ||
"terser": "^4.4.2" | ||
}, | ||
"scripts": { | ||
"benchmark": "babel-node benchmark.js", | ||
"build": "mkdirp build && browserify ./src/baobab.js -s Baobab -o ./build/baobab.js && uglifyjs ./build/baobab.js -c -m -o ./build/baobab.min.js && node ./scripts/banner.js", | ||
"benchmark": "babel-node --presets @babel/preset-env benchmark.js", | ||
"build": "node ./scripts/build.js", | ||
"check": "npm test && npm run lint && npm run build", | ||
"dist": "babel ./src --out-dir dist", | ||
"dist": "babel ./src --out-dir dist --presets @babel/preset-env", | ||
"lint": "eslint -c eslint.config.js ./src ./test", | ||
"prepublish": "npm run dist", | ||
"test": "mocha -R spec --require babel-core/register ./test/endpoint.js" | ||
"prepublish": "npm run check && npm run dist", | ||
"test": "mocha -R spec --require ./test/register.js ./test/endpoint.js" | ||
}, | ||
@@ -53,25 +55,3 @@ "repository": { | ||
}, | ||
"homepage": "https://github.com/Yomguithereal/baobab", | ||
"browserify": { | ||
"transform": [ | ||
[ | ||
"babelify", | ||
{ | ||
"presets": [ | ||
[ | ||
"es2015", | ||
{ | ||
"loose": true | ||
} | ||
] | ||
] | ||
} | ||
] | ||
] | ||
}, | ||
"babel": { | ||
"presets": [ | ||
"es2015" | ||
] | ||
} | ||
"homepage": "https://github.com/Yomguithereal/baobab" | ||
} |
@@ -11,3 +11,3 @@ [![Build Status](https://travis-ci.org/Yomguithereal/baobab.svg)](https://travis-ci.org/Yomguithereal/baobab) | ||
**Fun fact**: A [Baobab](http://en.wikipedia.org/wiki/Adansonia_digitata), or *Adansonia digitata*, is a very big and magnificient African tree. | ||
**Fun fact**: A [Baobab](http://en.wikipedia.org/wiki/Adansonia_digitata), or *Adansonia digitata*, is a very big and magnificent African tree. | ||
@@ -1055,3 +1055,3 @@ ## Summary | ||
User interfacess should be, as far as possible, considered as pure functions. Baobab is just a way to provide the needed arguments, i.e. the data representing your app's state, to such a function. | ||
User interfaces should be, as far as possible, considered as pure functions. Baobab is just a way to provide the needed arguments, i.e. the data representing your app's state, to such a function. | ||
@@ -1058,0 +1058,0 @@ Considering your UIs like pure functions comes along with collateral advantages like easy undo/redo features, state storing (just save your tree in the `localStorage` and here you go) and easy usage in both client & server. |
@@ -586,3 +586,3 @@ /** | ||
*/ | ||
Baobab.VERSION = '2.5.2'; | ||
Baobab.VERSION = '2.5.3'; | ||
@@ -589,0 +589,0 @@ /** |
Sorry, the diff of this file is not supported yet
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
208533
16
4974