vivisector
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -5,3 +5,4 @@ "use strict"; | ||
defineAddEventListener = _require.defineAddEventListener, | ||
defineRemoveEventListener = _require.defineRemoveEventListener; | ||
defineRemoveEventListener = _require.defineRemoveEventListener, | ||
raiseEvent = _require.raiseEvent; | ||
@@ -19,3 +20,3 @@ function ObservableArray(items) { | ||
function defineIndexProperty(index) { | ||
var defineIndexProperty = function defineIndexProperty(index) { | ||
if (!(index in _self)) { | ||
@@ -34,14 +35,8 @@ Object.defineProperty(_self, index, { | ||
item: inboundItem | ||
}); | ||
}, _self, _handlers); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
function raiseEvent(event) { | ||
_handlers[event.type].forEach(function (handler) { | ||
handler.call(_self, event); | ||
}); | ||
} | ||
Object.defineProperty(_self, "value", { | ||
@@ -60,3 +55,3 @@ configurable: false, | ||
item: inboundItems | ||
}); | ||
}, _self, _handlers); | ||
} | ||
@@ -90,6 +85,10 @@ } | ||
for (var i = 0, argsLen = arguments.length; i < argsLen; i++) { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
args.forEach(function (item) { | ||
index = _array.length; | ||
_array.push(i < 0 || arguments.length <= i ? undefined : arguments[i]); | ||
_array.push(item); | ||
@@ -100,6 +99,5 @@ defineIndexProperty(index); | ||
index: index, | ||
item: i < 0 || arguments.length <= i ? undefined : arguments[i] | ||
}); | ||
} | ||
item: item | ||
}, _self, _handlers); | ||
}); | ||
return _array.length; | ||
@@ -113,3 +111,3 @@ } | ||
value: function value() { | ||
if (_array.length > -1) { | ||
if (_array.length > 0) { | ||
var index = _array.length - 1, | ||
@@ -123,3 +121,3 @@ item = _array.pop(); | ||
item: item | ||
}); | ||
}, _self, _handlers); | ||
return item; | ||
@@ -134,20 +132,26 @@ } | ||
value: function value() { | ||
for (var i = 0, argsLen = arguments.length; i < argsLen; i++) { | ||
_array.splice(i, 0, i < 0 || arguments.length <= i ? undefined : arguments[i]); | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
args.forEach(function (item, index) { | ||
_array.splice(index, 0, item); | ||
defineIndexProperty(_array.length - 1); | ||
raiseEvent({ | ||
type: "itemadded", | ||
index: i, | ||
item: i < 0 || arguments.length <= i ? undefined : arguments[i] | ||
}); | ||
} | ||
index: index, | ||
item: item | ||
}, _self, _handlers); | ||
}); | ||
for (; i < _array.length; i++) { | ||
raiseEvent({ | ||
type: "itemset", | ||
index: i, | ||
item: _array[i] | ||
}); | ||
} | ||
_array.forEach(function (item, index) { | ||
if (index >= args.length) { | ||
raiseEvent({ | ||
type: "itemset", | ||
index: index, | ||
item: item | ||
}, _self, _handlers); | ||
} | ||
}); | ||
@@ -162,3 +166,3 @@ return _array.length; | ||
value: function value() { | ||
if (_array.length > -1) { | ||
if (_array.length > 0) { | ||
var item = _array.shift(); | ||
@@ -171,3 +175,3 @@ | ||
item: item | ||
}); | ||
}, _self, _handlers); | ||
return item; | ||
@@ -182,10 +186,16 @@ } | ||
value: function value() { | ||
var index = arguments.length <= 0 ? undefined : arguments[0]; | ||
var numElements = arguments.length <= 1 ? undefined : arguments[1]; | ||
var removed = []; | ||
var item, pos; | ||
for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = arguments[_key3]; | ||
} | ||
var index = args[0], | ||
numToRemove = args[1], | ||
itemsToAdd = args.slice(2), | ||
item; | ||
index = index == null ? 0 : index < 0 ? _array.length + index : index; | ||
numElements = numElements == null ? _array.length - index : numElements > 0 ? numElements : 0; | ||
numToRemove = numToRemove == null ? _array.length - index : numToRemove > 0 ? numToRemove : 0; | ||
while (numElements--) { | ||
while (numToRemove--) { | ||
item = _array.splice(index, 1)[0]; | ||
@@ -198,7 +208,7 @@ removed.push(item); | ||
item: item | ||
}); | ||
}, _self, _handlers); | ||
} | ||
for (var i = 2, argsLen = arguments.length; i < argsLen; i++) { | ||
_array.splice(index, 0, i < 0 || arguments.length <= i ? undefined : arguments[i]); | ||
itemsToAdd.forEach(function (item) { | ||
_array.splice(index, 0, item); | ||
@@ -209,7 +219,6 @@ defineIndexProperty(_array.length - 1); | ||
index: index, | ||
item: i < 0 || arguments.length <= i ? undefined : arguments[i] | ||
}); | ||
item: item | ||
}, _self, _handlers); | ||
index++; | ||
} | ||
}); | ||
return removed; | ||
@@ -225,16 +234,16 @@ } | ||
set: function set(value) { | ||
var ephemeralLength = Number(value); | ||
var symbolicLength = Number(value); | ||
var length = _array.length; | ||
if (ephemeralLength % 1 === 0 && ephemeralLength >= 0) { | ||
if (ephemeralLength < length) { | ||
_self.splice(ephemeralLength); | ||
} else if (ephemeralLength > length) { | ||
Reflect.apply(_self.push, _self, new Array(ephemeralLength - length)); | ||
if (symbolicLength % 1 === 0 && symbolicLength >= 0) { | ||
if (symbolicLength < length) { | ||
_self.splice(symbolicLength); | ||
} else if (symbolicLength > length) { | ||
Reflect.apply(_self.push, _self, new Array(symbolicLength - length)); | ||
} | ||
} else { | ||
throw new RangeError("Error: Invalid array length."); | ||
} | ||
} else { | ||
throw new RangeError("Invalid array length."); | ||
} | ||
_array.length = ephemeralLength; | ||
_array.length = symbolicLength; | ||
} | ||
@@ -241,0 +250,0 @@ }); |
@@ -7,17 +7,21 @@ "use strict"; | ||
defineAddEventListener = _require.defineAddEventListener, | ||
defineRemoveEventListener = _require.defineRemoveEventListener; | ||
defineRemoveEventListener = _require.defineRemoveEventListener, | ||
raiseEvent = _require.raiseEvent; | ||
function ObservableObject(obj) { | ||
var _self; | ||
var _handlers = { | ||
var _symbols = { | ||
__INTERNAL__: Symbol["for"]("_internal"), | ||
__ISPROXY__: Symbol["for"]("_isProxy") | ||
}, | ||
_handlers = { | ||
itemget: [], | ||
itemdeleted: [], | ||
itemset: [] | ||
}; | ||
}, | ||
_internals = ["addEventListener", "removeEventListener", "identifier", "type"]; | ||
var raiseEvent = function raiseEvent(event) { | ||
_handlers[event.type].forEach(function (handler) { | ||
handler.call(_self, event); | ||
}); | ||
var enforceConfigurableProps = function enforceConfigurableProps(prop) { | ||
if (_internals.includes(prop)) { | ||
throw new Error("Error: Property '".concat(prop, "' is non-configurable.")); | ||
} | ||
}; | ||
@@ -27,6 +31,10 @@ | ||
get: function get(target, prop, recv) { | ||
if (prop === Symbol["for"]("_isProxy")) { | ||
if (prop === _symbols.__ISPROXY__) { | ||
return true; | ||
} | ||
if (prop === _symbols.__INTERNAL__) { | ||
return target; | ||
} | ||
var value = Reflect.get(target, prop, recv); | ||
@@ -38,3 +46,3 @@ | ||
if (value) { | ||
if (value && !_internals.includes(prop)) { | ||
raiseEvent({ | ||
@@ -45,3 +53,3 @@ type: "itemget", | ||
value: value | ||
}); | ||
}, this, _handlers); | ||
} | ||
@@ -52,2 +60,3 @@ | ||
set: function set(target, prop, value, recv) { | ||
enforceConfigurableProps(prop); | ||
raiseEvent({ | ||
@@ -58,6 +67,7 @@ type: "itemset", | ||
value: value | ||
}); | ||
}, this, _handlers); | ||
return Reflect.set(target, prop, value); | ||
}, | ||
deleteProperty: function deleteProperty(target, prop) { | ||
enforceConfigurableProps(prop); | ||
var ephemeralTarget = JSON.stringify(target, null, 0); | ||
@@ -70,3 +80,3 @@ var value = Reflect.deleteProperty(target, prop); | ||
value: value | ||
}); | ||
}, this, _handlers); | ||
return value; | ||
@@ -80,3 +90,14 @@ } | ||
_self = new Proxy(Object.assign({}, obj), _rootHandler); | ||
var _self = new Proxy(JSON.parse(JSON.stringify(obj)), _rootHandler); | ||
Object.defineProperty(_self, "value", { | ||
configurable: false, | ||
enumerable: false, | ||
get: function get() { | ||
return Object.assign({}, _self[_symbols.__INTERNAL__]); | ||
}, | ||
set: function set(inboundItems) { | ||
return; | ||
} | ||
}); | ||
defineAddEventListener(_self, _handlers); | ||
@@ -83,0 +104,0 @@ defineRemoveEventListener(_self, _handlers); |
@@ -5,3 +5,4 @@ "use strict"; | ||
defineAddEventListener = _require.defineAddEventListener, | ||
defineRemoveEventListener = _require.defineRemoveEventListener; | ||
defineRemoveEventListener = _require.defineRemoveEventListener, | ||
raiseEvent = _require.raiseEvent; | ||
@@ -18,8 +19,2 @@ function ObservableString(value) { | ||
function raiseEvent(event) { | ||
_handlers[event.type].forEach(function (handler) { | ||
handler.call(_self, event); | ||
}); | ||
} | ||
function mutateCoreValue(coreObject, coreValue) { | ||
@@ -47,3 +42,3 @@ var value = coreObject[0].valueOf(); | ||
type: "mutated" | ||
}, mutateCoreValue(_self, arg))); | ||
}, mutateCoreValue(_self, arg)), _self, _handlers); | ||
} | ||
@@ -58,3 +53,3 @@ } | ||
if (!(typeof arg === "string")) { | ||
throw new Error("Invalid type"); | ||
throw new Error("Error: Invalid type."); | ||
} | ||
@@ -64,3 +59,3 @@ | ||
type: "mutated" | ||
}, mutateCoreValue(_self, arg))); | ||
}, mutateCoreValue(_self, arg)), _self, _handlers); | ||
return _self; | ||
@@ -67,0 +62,0 @@ } |
@@ -42,3 +42,3 @@ "use strict"; | ||
} else { | ||
throw new Error("Error: datatype ".concat(datatype, " is not available as an Observable.")); | ||
throw new Error("Error: datatype ".concat(datatype, " is not a supported option.")); | ||
} | ||
@@ -45,0 +45,0 @@ |
@@ -12,7 +12,7 @@ "use strict"; | ||
if (!(eventName in handlers)) { | ||
throw new Error("Invalid event name."); | ||
throw new Error("Error: Invalid event name."); | ||
} | ||
if (typeof handler !== "function") { | ||
throw new Error("Invalid handler."); | ||
throw new Error("Error: Invalid handler."); | ||
} | ||
@@ -35,7 +35,7 @@ | ||
if (!(eventName in handlers)) { | ||
throw new Error("Invalid event name."); | ||
throw new Error("Error: Invalid event name."); | ||
} | ||
if (typeof handler !== "function") { | ||
throw new Error("Invalid handler."); | ||
throw new Error("Error: Invalid handler."); | ||
} | ||
@@ -57,5 +57,12 @@ | ||
var raiseEvent = function raiseEvent(event, context, handlers) { | ||
handlers[event.type].forEach(function (handler) { | ||
handler.call(context, event); | ||
}); | ||
}; | ||
module.exports = { | ||
defineAddEventListener: defineAddEventListener, | ||
defineRemoveEventListener: defineRemoveEventListener | ||
defineRemoveEventListener: defineRemoveEventListener, | ||
raiseEvent: raiseEvent | ||
}; |
{ | ||
"name": "vivisector", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "node.js library for creating observable datatypes", | ||
@@ -18,6 +18,6 @@ "main": "./lib/index.js", | ||
"global": { | ||
"branches": 85, | ||
"branches": 95, | ||
"functions": 100, | ||
"lines": 95, | ||
"statements": 95 | ||
"lines": 100, | ||
"statements": 100 | ||
} | ||
@@ -24,0 +24,0 @@ } |
134
README.md
@@ -1,9 +0,8 @@ | ||
<img src="https://github.com/MatthewZito/vivisector-js/blob/master/documentation/vx.png" width="390" height="390"> | ||
![Vivisector Logo](https://github.com/MatthewZito/vivisector-js/blob/master/documentation/vx.png) | ||
# Vivisector.js | Create observable JavaScript datatypes | ||
[![Coverage Status](https://coveralls.io/repos/github/MatthewZito/vivisector-js/badge.svg?branch=master)](https://coveralls.io/github/MatthewZito/vivisector-js?branch=master) | ||
``` | ||
Author: Matthew T Zito | ||
License: MIT | ||
``` | ||
[![npm version](https://badge.fury.io/js/vivisector.svg)](https://badge.fury.io/js/vivisector) | ||
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) | ||
## Table of Contents | ||
@@ -15,6 +14,3 @@ | ||
- [Documentation](#docs) | ||
* [About](#about) | ||
## *Listen to Arrays or Objects, even Strings for changes with Vivisector.js* | ||
## <a name="intro"></a> Introduction | ||
@@ -32,4 +28,6 @@ *Vivisector.js* is a light-weight Nodejs library that exposes custom event-driven datatypes. *Vivisector's* *Observable* types broadcast unique events correlated to specific types of mutations and accessors. As such, one can bind methods to variables and render them event-bound. | ||
- no need to use `new` keyword, no configuration; `Vivisector` types work out-of-the-box | ||
- absolutely zero dependencies | ||
## <a name="usage"></a> Installation and Usage | ||
[Install via NPM](https://www.npmjs.com/package/vivisector) with `npm i vivisector`. | ||
@@ -63,10 +61,9 @@ Import *Vivisector's* caller alias `Vx`: | ||
Full wiki coming soon... | ||
### Vivisector Types | ||
### `Vivisector` Types | ||
#### `ObservableArray` (*extends `Array`*) | ||
#### ObservableArray (*extends Array*) | ||
*an Array-like Object* | ||
**Unique Methods and Props** | ||
- **`findIndexAll`** Returns an Array of all indices that contain a match to given argument. | ||
- **findIndexAll** Returns an Array of all indices that contain a match to given argument. | ||
@@ -80,37 +77,37 @@ ``` | ||
**Event Types** | ||
- **`itemadded`** A new item has been added to the Array. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemadded", denoting the event-type that was triggered | ||
- **`item`** the new item, now added to the Array, | ||
- **`index`** the index at which the item was added | ||
- **itemadded** A new item has been added to the Array. Callbacks will receive an Object consisting of | ||
- **type** String "itemadded", denoting the event-type that was triggered | ||
- **item** the new item, now added to the Array, | ||
- **index** the index at which the item was added | ||
**Fires on:** *`push`, `unshift`, `splice`* | ||
**Fires on:** *push, unshift, splice* | ||
- **`itemset`** An item in the Array has moved. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemset", denoting the event-type that was triggered | ||
- **`item`** the item set in the Array | ||
- **`index`** the index to which the item was allocated | ||
- **itemset** An item in the Array has moved. Callbacks will receive an Object consisting of | ||
- **type** String "itemset", denoting the event-type that was triggered | ||
- **item** the item set in the Array | ||
- **index** the index to which the item was allocated | ||
**Fires on:** *`unshift`, using index accessors to set Array items* | ||
**Fires on:** *unshift, using index accessors to set Array items* | ||
**Note:** Shuffling the Array or using methods like `unshift` will fire `itemset` for *each* index change | ||
- **`itemremoved`** An item has been removed from the Array. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemremoved", denoting the event-type that was triggered | ||
- **`item`** the item removed from the Array, | ||
- **`index`** the index at which the item was removed | ||
- **itemremoved** An item has been removed from the Array. Callbacks will receive an Object consisting of | ||
- **type** String "itemremoved", denoting the event-type that was triggered | ||
- **item** the item removed from the Array, | ||
- **index** the index at which the item was removed | ||
**Fires on:** *`pop`, `shift`, `splice`* | ||
**Fires on:** *pop, shift, splice* | ||
- **`mutated`** The Array value has been reassigned. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "mutated", denoting the event-type that was triggered | ||
- **`item`** the new Array value, | ||
- **`index`** "all", String - all indices will have been affected | ||
- **mutated** The Array value has been reassigned. Callbacks will receive an Object consisting of | ||
- **type** String "mutated", denoting the event-type that was triggered | ||
- **item** the new Array value, | ||
- **index** "all", String - all indices will have been affected | ||
**Fires on:** *Using the `value` accessor to mutate the Array value* | ||
**Fires on:** *Using the value accessor to mutate the Array value* | ||
#### `ObservableString` (*extends `String`*) | ||
#### ObservableString (*extends String*) | ||
*a mutable, String-like Object* | ||
**Unique Methods and Props** | ||
- **`reassign`** Mutates String value, chainable (returns `this`). | ||
- **reassign** Mutates String value, chainable (returns `this`). | ||
@@ -125,32 +122,32 @@ ``` | ||
- **`length`** Returns String value length; non-configurable. | ||
- **length** Returns String value length; non-configurable. | ||
**Event Types** | ||
- **`mutated`** The String value has been reassigned. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "mutated", denoting the event-type that was triggered | ||
- **`value`** the previous String value, | ||
- **`mutant`** the reassigned String value | ||
- **mutated** The String value has been reassigned. Callbacks will receive an Object consisting of | ||
- **type** String "mutated", denoting the event-type that was triggered | ||
- **value** the previous String value, | ||
- **mutant** the reassigned String value | ||
#### `ObservableObject` (*extends Proxy*) | ||
#### ObservableObject (*extends Proxy*) | ||
*an extended Object Proxy* | ||
**Event Types** | ||
- **`itemget`** An Object property value has been accessed. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemget", denoting the event-type that was triggered | ||
- **`prop`** The name or Symbol of the property being accessed | ||
- **`target`** The target object | ||
- **`value`** The specific value being accessed | ||
- **`itemset`** An Object property value has been set. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemset", denoting the event-type that was triggered | ||
- **`prop`** The name or Symbol of the property being set | ||
- **`target`** The target object | ||
- **`value`** The new value that has been set on `prop` | ||
- **`itemdeleted`** An Object property value has been deleted. Callbacks will receive an `events` Object consisting of | ||
- **`type`** String "itemdeleted", denoting the event-type that was triggered | ||
- **`prop`** The name or Symbol of the property being deleted | ||
- **`target`** The stringified target object | ||
- **`value`** A Boolean value indicating deletion success | ||
- **itemget** An Object property value has been accessed. Callbacks will receive an Object consisting of | ||
- **type** String "itemget", denoting the event-type that was triggered | ||
- **prop** The name or Symbol of the property being accessed | ||
- **target** The target object | ||
- **value** The specific value being accessed | ||
- **itemset** An Object property value has been set. Callbacks will receive an Object consisting of | ||
- **type** String "itemset", denoting the event-type that was triggered | ||
- **prop** The name or Symbol of the property being set | ||
- **target** The target object | ||
- **value** The new value that has been set on `prop` | ||
- **itemdeleted** An Object property value has been deleted. Callbacks will receive an Object consisting of | ||
- **type** String "itemdeleted", denoting the event-type that was triggered | ||
- **prop** The name or Symbol of the property being deleted | ||
- **target** The stringified target object | ||
- **value** A Boolean value indicating deletion success | ||
### `Vivisector` Ubiquitous Methods and Props | ||
- **`value`** A non-enumerable accessor for getting/setting the core value of a given *Observable* | ||
### Vivisector Ubiquitous Methods and Props | ||
- **value** A non-enumerable accessor for getting and/or setting the core value of a given *Observable* | ||
@@ -165,6 +162,9 @@ ``` | ||
``` | ||
*Get/Set on types `String`, `Array`* | ||
*Get on types `Object`* | ||
- **`identifier`** A unique identifier assigned to all *Observables*. Namespace confined to the Nodejs runtime's `global`, or 'module context'. Currently a paused feature. | ||
- **`type`** The type identifier of a given *Observable*, *e.g. "Array", "Object", "String"* | ||
- **`addEventListener`** Bind a callback to fire whenever a given event-type has been triggered. | ||
- **identifier** A unique identifier assigned to all *Observables*. Namespace confined to the Nodejs runtime's `global`, or 'module context'. Currently a paused feature. | ||
- **type** The type identifier of a given *Observable*, *e.g. "Array", "Object", "String"* | ||
- **addEventListener** Bind a callback to fire whenever a given event-type has been triggered. | ||
@@ -182,3 +182,3 @@ ``` | ||
- **`removeEventListener`** Remove an existing callback from the respective event-type to which it has been registered. | ||
- **removeEventListener** Remove an existing callback from the respective event-type to which it has been registered. | ||
@@ -195,12 +195,2 @@ ``` | ||
// no log - handler was removed ^ | ||
``` | ||
<hr> | ||
### <a name="about"></a> About | ||
*How can we listen to changes in an Object or Array, or even a String?* | ||
This is the question I set out to answer when I started writing `ObservableArrays`. I read about things like Rxjs or the *Observer pattern* but found in them paradigms far too complex for what I was trying to do: simply fire events when variables had changed (and contingent on *what* those changes were). And so I continued with the creation of *Vivisector.js*, a very light-weight (and dependency-free) library for creating 'Observable' datatypes. | ||
For example, we can instantiate a new *Observable* of type `Array` and we will have available to us an Array-like object which extends native Array methods and properties, but is also equipped with the capacity to become event-bound. That is, *Vivisector* gives you an Array onto which you can bind (and chain) events. | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
33174
518
188