New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

vivisector

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vivisector - npm Package Compare versions

Comparing version 1.5.1 to 1.6.0

429

dist/vivisector.cjs.js

@@ -29,4 +29,4 @@

/* global Reflect, Promise */
var _extendStatics = function extendStatics(d, b) {
_extendStatics = Object.setPrototypeOf || {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf || {
__proto__: []

@@ -36,8 +36,6 @@ } instanceof Array && function (d, b) {

} || function (d, b) {
for (var p in b) {
if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
}
for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
};
return _extendStatics(d, b);
return extendStatics(d, b);
};

@@ -47,5 +45,4 @@

if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
_extendStatics(d, b);
function __() {

@@ -67,6 +64,8 @@ this.constructor = d;

var unboundedSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundedSlice);
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
/**
* @summary Shallow copy an object or array
*
* @internal
*/

@@ -81,12 +80,12 @@ function shallowCopy(base) {

var key = keys[i];
var desc = descriptors[key];
if (!desc.writable) {
desc.writable = true;
desc.configurable = true;
var descriptor = descriptors[key];
if (!descriptor.writable) {
descriptor.writable = true;
descriptor.configurable = true;
}
if (desc.get || desc.set) {
if (descriptor.get || descriptor.set) {
descriptors[key] = {
configurable: true,
writable: !!desc.set,
enumerable: desc.enumerable,
writable: !!descriptor.set,
enumerable: descriptor.enumerable,
value: base[key]

@@ -100,5 +99,6 @@ };

* @summary Define a non-configurable function property `value` with name `name` on a given object `context`
* @param {VxState} context The object on which the property will be defined
* @param {string} name The name of the property
* @param {Function} value The value of the function property
* @param name The name of the property
* @param value The value of the function property
*
* @internal
*/

@@ -116,10 +116,10 @@ function defineNonConfigurableProp(context, name, value) {

* and whether a given property exists on that array's prototype
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/
function isArrayProto(target, prop) {
return Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype)
.includes(prop);
return (Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype).includes(prop));
}

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

* and whether it is out of bounds relative to a given target
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/

@@ -138,3 +139,3 @@ function isArrayPropOutOfBounds(target, prop) {

return false;
return Array.isArray(target) && (maybeIdx > (target.length - 1));
return Array.isArray(target) && maybeIdx > target.length - 1;
}

@@ -144,2 +145,4 @@

* @summary Base implementation model for extended errors
*
* @internal
*/

@@ -160,2 +163,4 @@ var BaseVxError = /** @class */ (function (_super) {

* Base implementation for errors
*
* @internal
*/

@@ -173,2 +178,4 @@ var VxError = /** @class */ (function (_super) {

* @summary Exception metadata builder
*
* @internal
*/

@@ -183,4 +190,3 @@ var VxException = /** @class */ (function () {

* @summary Build an error object with the given exception metadata instance
* @param {VxException} instance
* @returns {VxError}
* @param instance
*/

@@ -192,3 +198,2 @@ VxException.create = function (instance) {

* @summary Serialize the source metadata into a string
* @returns {string}
*/

@@ -199,10 +204,9 @@ VxException.prototype.serializeSource = function () {

var _a = this.source, filename = _a.filename, lineno = _a.lineno;
return "at " + filename + ", Ln " + lineno;
return " at " + filename + ", Ln " + lineno;
};
/**
* @summary Serialize the exception metadata into a string
* @returns {string}
*/
VxException.prototype.serialize = function () {
return this.reason + " " + this.serializeSource();
return "" + this.reason + this.serializeSource();
};

@@ -213,105 +217,51 @@ return VxException;

/**
* @summary Validate a provided event handler name, value
* @param {string} eventName
* @param {Function} handler
* @see https://github.com/microsoft/TypeScript/issues/26916
*/
function validateEventHandler(eventName, handler) {
if (!(eventName in this.handlerStore)) {
/**
* @summary Validate a provided event handler
* @param handler
*
* @internal
*/
function validateEventHandler(handler) {
if (typeof handler !== 'function') {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
reason: 'The provided event handler must be a function'
}));
}
else if (typeof handler !== 'function') {
}
/**
* @summary Validate a provided event name
* @param eventName
* @param validEvents - a list of possible valid event names
*
* @internal
*/
function validateEventName(eventName, validEvents) {
if (typeof eventName !== 'string') {
throw VxException.create(new VxException({
reason: 'The provided event handler must be a function'
reason: "Event name must be a string"
}));
}
if (!validEvents.includes(eventName)) {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
}));
}
}
/**
* @summary Evaluate whether `testValue` is a plain object
* @param testValue
*
* @internal
*/
var isObject = function (testValue) {
return {}.toString.call(testValue) == '[object Object]';
};
var VX_EVENT_TYPE;
(function (VX_EVENT_TYPE) {
VX_EVENT_TYPE["ADD"] = "add";
VX_EVENT_TYPE["DEL"] = "del";
VX_EVENT_TYPE["SET"] = "set";
VX_EVENT_TYPE["BATCHED"] = "batched";
})(VX_EVENT_TYPE || (VX_EVENT_TYPE = {}));
var VX_LISTENER_INTERNALS;
(function (VX_LISTENER_INTERNALS) {
VX_LISTENER_INTERNALS["ADD"] = "addEventListener";
VX_LISTENER_INTERNALS["REM"] = "removeEventListener";
})(VX_LISTENER_INTERNALS || (VX_LISTENER_INTERNALS = {}));
/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
* @summary Construct a done committal function
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
var _a;
/**
* Event-correlated handlers; below are defaults
* @property {VxEventHandlerStore}
*/
this.handlerStore = (_a = {},
_a[VX_EVENT_TYPE.ADD] = new Set(),
_a[VX_EVENT_TYPE.DEL] = new Set(),
_a[VX_EVENT_TYPE.SET] = new Set(),
_a[VX_EVENT_TYPE.BATCHED] = new Set(),
_a);
this.internals = __spreadArray([], Object.values(VX_LISTENER_INTERNALS));
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param {string|symbol} prop The property presently being accessed
* @returns {boolean}
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `addEventListener`, `removeEventListener` on the proxied object
* @param context The context (i.e. `this` instance) of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineListeners = function (context) {
var _this = this;
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.ADD, function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventHandler.call(_this, eventName, handler);
_this.handlerStore[eventName]
.add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.REM, function (eventName, handler) {
validateEventHandler.call(_this, eventName, handler);
var handlers = _this.handlerStore[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param {object} event An object containing data about the event
* @param {object} context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, context, done) {
this.handlerStore[event.type]
.forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler.call(context, event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
var DoneFunctionBuilder = function (ret) {

@@ -325,4 +275,10 @@ var done = function (commit) {

var eventedArrayPrototypeResolver = function (target, prop) {
var _this = this;
/**
* @summary Define evented analogs on a proxied array prototype
* @param target
* @param prop
*
* @internal
*/
function eventedArrayPrototypeResolver(context, target, prop) {
var ogMethod = target[prop];

@@ -338,8 +294,10 @@ return function () {

var ret = nextState.shift();
var done = DoneFunctionBuilder(function () { return Array.prototype.shift.call(target); });
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
var done = DoneFunctionBuilder(function () {
return Array.prototype.shift.call(target);
});
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -352,7 +310,7 @@ }

});
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
context.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -365,10 +323,10 @@ }

var _a;
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args));
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args, false));
});
ret = nextState.unshift.apply(nextState, args);
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
}

@@ -380,7 +338,7 @@ return ret;

nextState.reverse();
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState;

@@ -391,7 +349,7 @@ }

nextState.push.apply(nextState, args);
_this.raiseEvent({
type: args.length > 1 ? VX_EVENT_TYPE.BATCHED : VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: args.length > 1 ? 'batched' : 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState.length;

@@ -403,7 +361,7 @@ }

ogMethod.apply(nextState, [arg]);
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
prevState = shallowCopy(target);

@@ -420,18 +378,12 @@ };

};
};
}
var batchedMethods = [
'shift',
'unshift',
'push',
'reverse',
'sort',
'pop'
];
var batchedMethods = ['shift', 'unshift', 'push', 'reverse', 'sort', 'pop'];
/**
* @summary Construct a base proxy handler with an implicit context
* @returns {ProxyHandler<VxState>} Base proxy handler
* @returns {ProxyHandler<?>} Base proxy handler
*
* @internal
*/
function RootHandlerFactory() {
var _this = this;
function RootHandlerFactory(base) {
var rootHandler = {

@@ -447,3 +399,3 @@ get: function (target, prop, recv) {

if (Array.isArray(target) && batchedMethods.includes(prop)) {
return eventedArrayPrototypeResolver.call(_this, target, prop);
return eventedArrayPrototypeResolver(base, target, prop);
}

@@ -460,3 +412,3 @@ // we use reflection to mitigate violation of Proxy invariants, as described in the specification here:

set: function (target, prop, value) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -469,15 +421,16 @@ }

var ret = Reflect.set(nextState, prop, value);
var done = DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); });
if (!(prop in prevState) || isArrayPropOutOfBounds(prevState, prop)) {
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
base.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}
else {
_this.raiseEvent({
type: VX_EVENT_TYPE.SET,
base.raiseEvent({
type: 'set',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}

@@ -487,3 +440,3 @@ return ret;

deleteProperty: function (target, prop) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -493,9 +446,12 @@ }

var ret = true;
// tested via public API
// istanbul ignore next
if (Array.isArray(nextState)) {
nextState.splice(Number(prop), 1);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
var numericProp_1 = Number(prop);
nextState.splice(numericProp_1, 1);
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return target.splice(Number(prop), 1); }));
}, DoneFunctionBuilder(function () { return target.splice(numericProp_1, 1); }));
return ret;

@@ -505,9 +461,10 @@ }

Reflect.deleteProperty(nextState, prop);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
}, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
return ret;
}
// istanbul ignore next
return ret;

@@ -519,13 +476,99 @@ }

/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
/**
* Event-correlated handlers; below are defaults
*/
this.observers = {
add: new Set(),
del: new Set(),
set: new Set(),
batched: new Set()
};
this.internals = ['subscribe', 'unsubscribe'];
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param prop The property presently being accessed
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
// see -> https://github.com/microsoft/TypeScript/issues/26255
// btw, this is where TypeScript's bizarre `Array.prototype.includes` approach could screw us over
// if I followed TS' way, I may only pass a string to `includes`, which means if we receive a symbol, we'll return false
// which would propagate to the proxy and lead to a invariant violation
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `subscribe`, `unsubscribe` on the proxied object
* @param context The context of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineSubscribers = function (context) {
var _this = this;
defineNonConfigurableProp(context, 'subscribe', function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventName(eventName, Object.keys(_this.observers));
validateEventHandler(handler);
_this.observers[eventName].add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, 'unsubscribe', function (eventName, handler) {
// both validators are tested via the public API
// istanbul ignore next
validateEventName(eventName, Object.keys(_this.observers));
// istanbul ignore next
validateEventHandler(handler);
var handlers = _this.observers[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param event An object containing data about the event
* @param context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, done) {
this.observers[event.type].forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
// tested via public API
// istanbul ignore next
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler(event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
/**
* @summary Create proxies
*
* @internal
*/
var ProxiedObservableFactory = /** @class */ (function (_super) {
__extends(ProxiedObservableFactory, _super);
function ProxiedObservableFactory() {
var _this = _super.call(this) || this;
_this.rootHandler = RootHandlerFactory
.call(_this);
return _this;
return _super !== null && _super.apply(this, arguments) || this;
}
ProxiedObservableFactory.prototype.create = function (initialState) {
/**
* @summary Root Proxy handler; injects event broadcasts into get|set|delete traps
*/
ProxiedObservableFactory.create = function (initialState) {
var excisedInitialState = shallowCopy(initialState);
return this.defineListeners(new Proxy(excisedInitialState, this.rootHandler));
var instance = new ProxiedObservableFactory();
return instance.defineSubscribers(new Proxy(excisedInitialState, RootHandlerFactory(instance)));
};

@@ -535,5 +578,19 @@ return ProxiedObservableFactory;

var vivisect = function (initialState) { return new ProxiedObservableFactory()
.create(initialState); };
/**
* @summary 'Vivisect' an object - render the object evented by
* proxying it through a subscribable interface
*
* @param initialState
*
* @public
*/
var vivisect = function (initialState) {
if (isObject(initialState) || Array.isArray(initialState)) {
return ProxiedObservableFactory.create(initialState);
}
throw VxException.create(new VxException({
reason: 'invalid initial state type'
}));
};
exports.vivisect = vivisect;

@@ -1,43 +0,34 @@

declare enum VX_EVENT_TYPE {
ADD = "add",
DEL = "del",
SET = "set",
BATCHED = "batched"
}
declare enum VX_LISTENER_INTERNALS {
ADD = "addEventListener",
REM = "removeEventListener"
}
interface VxEventedObject {
readonly [VX_LISTENER_INTERNALS.ADD]: VxEventRegistrar;
readonly [VX_LISTENER_INTERNALS.REM]: VxEventRegistrar;
[k: string]: any;
}
interface DoneFunction {
declare type ISubscriptionEvent = 'add' | 'del' | 'set' | 'batched';
declare type IVivisectorApi<S> = {
readonly subscribe: ISubscription<S>;
readonly unsubscribe: ISubscription<S>;
} & S;
interface IDoneFunction {
(commit: boolean): void;
}
interface VxAddEventListenerOpts {
interface ISubscriptionOpts {
alwaysCommit?: boolean;
}
interface VxEventRegistrar {
(eventName: VX_EVENT_TYPE, handler: VxEventHandler, opts?: VxAddEventListenerOpts): VxEventedObject;
interface ISubscription<S> {
(eventName: ISubscriptionEvent, handler: ISubscriptionCallback<S>, opts?: ISubscriptionOpts): IVivisectorApi<S>;
}
declare type VxState = object | any[];
declare type VxEvent<T extends VxState> = {
type: VX_EVENT_TYPE;
prevState: T;
nextState: T;
};
declare type VxEventHandler = (e: VxEvent<VxState>, done: DoneFunction) => void;
declare global {
interface Array<T> {
includes<U extends (T extends U ? unknown : never)>(el: U, idx?: number): boolean;
}
interface ISubscriptionCallback<S> {
(e: ISubscriptionEventMetadata<S>, done: IDoneFunction): void;
}
interface Vivisector {
(initialState: VxState): VxEventedObject;
interface ISubscriptionEventMetadata<S> {
type: ISubscriptionEvent;
prevState: S;
nextState: S;
}
declare const vivisect: Vivisector;
/**
* @summary 'Vivisect' an object - render the object evented by
* proxying it through a subscribable interface
*
* @param initialState
*
* @public
*/
declare const vivisect: <S>(initialState: S) => IVivisectorApi<S>;
export { vivisect };

@@ -25,4 +25,4 @@

/* global Reflect, Promise */
var _extendStatics = function extendStatics(d, b) {
_extendStatics = Object.setPrototypeOf || {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf || {
__proto__: []

@@ -32,8 +32,6 @@ } instanceof Array && function (d, b) {

} || function (d, b) {
for (var p in b) {
if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
}
for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
};
return _extendStatics(d, b);
return extendStatics(d, b);
};

@@ -43,5 +41,4 @@

if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
_extendStatics(d, b);
function __() {

@@ -63,6 +60,8 @@ this.constructor = d;

var unboundedSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundedSlice);
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
/**
* @summary Shallow copy an object or array
*
* @internal
*/

@@ -77,12 +76,12 @@ function shallowCopy(base) {

var key = keys[i];
var desc = descriptors[key];
if (!desc.writable) {
desc.writable = true;
desc.configurable = true;
var descriptor = descriptors[key];
if (!descriptor.writable) {
descriptor.writable = true;
descriptor.configurable = true;
}
if (desc.get || desc.set) {
if (descriptor.get || descriptor.set) {
descriptors[key] = {
configurable: true,
writable: !!desc.set,
enumerable: desc.enumerable,
writable: !!descriptor.set,
enumerable: descriptor.enumerable,
value: base[key]

@@ -96,5 +95,6 @@ };

* @summary Define a non-configurable function property `value` with name `name` on a given object `context`
* @param {VxState} context The object on which the property will be defined
* @param {string} name The name of the property
* @param {Function} value The value of the function property
* @param name The name of the property
* @param value The value of the function property
*
* @internal
*/

@@ -112,10 +112,10 @@ function defineNonConfigurableProp(context, name, value) {

* and whether a given property exists on that array's prototype
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/
function isArrayProto(target, prop) {
return Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype)
.includes(prop);
return (Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype).includes(prop));
}

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

* and whether it is out of bounds relative to a given target
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/

@@ -134,3 +135,3 @@ function isArrayPropOutOfBounds(target, prop) {

return false;
return Array.isArray(target) && (maybeIdx > (target.length - 1));
return Array.isArray(target) && maybeIdx > target.length - 1;
}

@@ -140,2 +141,4 @@

* @summary Base implementation model for extended errors
*
* @internal
*/

@@ -156,2 +159,4 @@ var BaseVxError = /** @class */ (function (_super) {

* Base implementation for errors
*
* @internal
*/

@@ -169,2 +174,4 @@ var VxError = /** @class */ (function (_super) {

* @summary Exception metadata builder
*
* @internal
*/

@@ -179,4 +186,3 @@ var VxException = /** @class */ (function () {

* @summary Build an error object with the given exception metadata instance
* @param {VxException} instance
* @returns {VxError}
* @param instance
*/

@@ -188,3 +194,2 @@ VxException.create = function (instance) {

* @summary Serialize the source metadata into a string
* @returns {string}
*/

@@ -195,10 +200,9 @@ VxException.prototype.serializeSource = function () {

var _a = this.source, filename = _a.filename, lineno = _a.lineno;
return "at " + filename + ", Ln " + lineno;
return " at " + filename + ", Ln " + lineno;
};
/**
* @summary Serialize the exception metadata into a string
* @returns {string}
*/
VxException.prototype.serialize = function () {
return this.reason + " " + this.serializeSource();
return "" + this.reason + this.serializeSource();
};

@@ -209,105 +213,51 @@ return VxException;

/**
* @summary Validate a provided event handler name, value
* @param {string} eventName
* @param {Function} handler
* @see https://github.com/microsoft/TypeScript/issues/26916
*/
function validateEventHandler(eventName, handler) {
if (!(eventName in this.handlerStore)) {
/**
* @summary Validate a provided event handler
* @param handler
*
* @internal
*/
function validateEventHandler(handler) {
if (typeof handler !== 'function') {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
reason: 'The provided event handler must be a function'
}));
}
else if (typeof handler !== 'function') {
}
/**
* @summary Validate a provided event name
* @param eventName
* @param validEvents - a list of possible valid event names
*
* @internal
*/
function validateEventName(eventName, validEvents) {
if (typeof eventName !== 'string') {
throw VxException.create(new VxException({
reason: 'The provided event handler must be a function'
reason: "Event name must be a string"
}));
}
if (!validEvents.includes(eventName)) {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
}));
}
}
/**
* @summary Evaluate whether `testValue` is a plain object
* @param testValue
*
* @internal
*/
var isObject = function (testValue) {
return {}.toString.call(testValue) == '[object Object]';
};
var VX_EVENT_TYPE;
(function (VX_EVENT_TYPE) {
VX_EVENT_TYPE["ADD"] = "add";
VX_EVENT_TYPE["DEL"] = "del";
VX_EVENT_TYPE["SET"] = "set";
VX_EVENT_TYPE["BATCHED"] = "batched";
})(VX_EVENT_TYPE || (VX_EVENT_TYPE = {}));
var VX_LISTENER_INTERNALS;
(function (VX_LISTENER_INTERNALS) {
VX_LISTENER_INTERNALS["ADD"] = "addEventListener";
VX_LISTENER_INTERNALS["REM"] = "removeEventListener";
})(VX_LISTENER_INTERNALS || (VX_LISTENER_INTERNALS = {}));
/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
* @summary Construct a done committal function
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
var _a;
/**
* Event-correlated handlers; below are defaults
* @property {VxEventHandlerStore}
*/
this.handlerStore = (_a = {},
_a[VX_EVENT_TYPE.ADD] = new Set(),
_a[VX_EVENT_TYPE.DEL] = new Set(),
_a[VX_EVENT_TYPE.SET] = new Set(),
_a[VX_EVENT_TYPE.BATCHED] = new Set(),
_a);
this.internals = __spreadArray([], Object.values(VX_LISTENER_INTERNALS));
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param {string|symbol} prop The property presently being accessed
* @returns {boolean}
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `addEventListener`, `removeEventListener` on the proxied object
* @param context The context (i.e. `this` instance) of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineListeners = function (context) {
var _this = this;
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.ADD, function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventHandler.call(_this, eventName, handler);
_this.handlerStore[eventName]
.add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.REM, function (eventName, handler) {
validateEventHandler.call(_this, eventName, handler);
var handlers = _this.handlerStore[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param {object} event An object containing data about the event
* @param {object} context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, context, done) {
this.handlerStore[event.type]
.forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler.call(context, event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
var DoneFunctionBuilder = function (ret) {

@@ -321,4 +271,10 @@ var done = function (commit) {

var eventedArrayPrototypeResolver = function (target, prop) {
var _this = this;
/**
* @summary Define evented analogs on a proxied array prototype
* @param target
* @param prop
*
* @internal
*/
function eventedArrayPrototypeResolver(context, target, prop) {
var ogMethod = target[prop];

@@ -334,8 +290,10 @@ return function () {

var ret = nextState.shift();
var done = DoneFunctionBuilder(function () { return Array.prototype.shift.call(target); });
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
var done = DoneFunctionBuilder(function () {
return Array.prototype.shift.call(target);
});
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -348,7 +306,7 @@ }

});
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
context.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -361,10 +319,10 @@ }

var _a;
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args));
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args, false));
});
ret = nextState.unshift.apply(nextState, args);
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
}

@@ -376,7 +334,7 @@ return ret;

nextState.reverse();
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState;

@@ -387,7 +345,7 @@ }

nextState.push.apply(nextState, args);
_this.raiseEvent({
type: args.length > 1 ? VX_EVENT_TYPE.BATCHED : VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: args.length > 1 ? 'batched' : 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState.length;

@@ -399,7 +357,7 @@ }

ogMethod.apply(nextState, [arg]);
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
prevState = shallowCopy(target);

@@ -416,18 +374,12 @@ };

};
};
}
var batchedMethods = [
'shift',
'unshift',
'push',
'reverse',
'sort',
'pop'
];
var batchedMethods = ['shift', 'unshift', 'push', 'reverse', 'sort', 'pop'];
/**
* @summary Construct a base proxy handler with an implicit context
* @returns {ProxyHandler<VxState>} Base proxy handler
* @returns {ProxyHandler<?>} Base proxy handler
*
* @internal
*/
function RootHandlerFactory() {
var _this = this;
function RootHandlerFactory(base) {
var rootHandler = {

@@ -443,3 +395,3 @@ get: function (target, prop, recv) {

if (Array.isArray(target) && batchedMethods.includes(prop)) {
return eventedArrayPrototypeResolver.call(_this, target, prop);
return eventedArrayPrototypeResolver(base, target, prop);
}

@@ -456,3 +408,3 @@ // we use reflection to mitigate violation of Proxy invariants, as described in the specification here:

set: function (target, prop, value) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -465,15 +417,16 @@ }

var ret = Reflect.set(nextState, prop, value);
var done = DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); });
if (!(prop in prevState) || isArrayPropOutOfBounds(prevState, prop)) {
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
base.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}
else {
_this.raiseEvent({
type: VX_EVENT_TYPE.SET,
base.raiseEvent({
type: 'set',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}

@@ -483,3 +436,3 @@ return ret;

deleteProperty: function (target, prop) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -489,9 +442,12 @@ }

var ret = true;
// tested via public API
// istanbul ignore next
if (Array.isArray(nextState)) {
nextState.splice(Number(prop), 1);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
var numericProp_1 = Number(prop);
nextState.splice(numericProp_1, 1);
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return target.splice(Number(prop), 1); }));
}, DoneFunctionBuilder(function () { return target.splice(numericProp_1, 1); }));
return ret;

@@ -501,9 +457,10 @@ }

Reflect.deleteProperty(nextState, prop);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
}, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
return ret;
}
// istanbul ignore next
return ret;

@@ -515,13 +472,99 @@ }

/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
/**
* Event-correlated handlers; below are defaults
*/
this.observers = {
add: new Set(),
del: new Set(),
set: new Set(),
batched: new Set()
};
this.internals = ['subscribe', 'unsubscribe'];
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param prop The property presently being accessed
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
// see -> https://github.com/microsoft/TypeScript/issues/26255
// btw, this is where TypeScript's bizarre `Array.prototype.includes` approach could screw us over
// if I followed TS' way, I may only pass a string to `includes`, which means if we receive a symbol, we'll return false
// which would propagate to the proxy and lead to a invariant violation
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `subscribe`, `unsubscribe` on the proxied object
* @param context The context of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineSubscribers = function (context) {
var _this = this;
defineNonConfigurableProp(context, 'subscribe', function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventName(eventName, Object.keys(_this.observers));
validateEventHandler(handler);
_this.observers[eventName].add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, 'unsubscribe', function (eventName, handler) {
// both validators are tested via the public API
// istanbul ignore next
validateEventName(eventName, Object.keys(_this.observers));
// istanbul ignore next
validateEventHandler(handler);
var handlers = _this.observers[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param event An object containing data about the event
* @param context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, done) {
this.observers[event.type].forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
// tested via public API
// istanbul ignore next
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler(event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
/**
* @summary Create proxies
*
* @internal
*/
var ProxiedObservableFactory = /** @class */ (function (_super) {
__extends(ProxiedObservableFactory, _super);
function ProxiedObservableFactory() {
var _this = _super.call(this) || this;
_this.rootHandler = RootHandlerFactory
.call(_this);
return _this;
return _super !== null && _super.apply(this, arguments) || this;
}
ProxiedObservableFactory.prototype.create = function (initialState) {
/**
* @summary Root Proxy handler; injects event broadcasts into get|set|delete traps
*/
ProxiedObservableFactory.create = function (initialState) {
var excisedInitialState = shallowCopy(initialState);
return this.defineListeners(new Proxy(excisedInitialState, this.rootHandler));
var instance = new ProxiedObservableFactory();
return instance.defineSubscribers(new Proxy(excisedInitialState, RootHandlerFactory(instance)));
};

@@ -531,5 +574,19 @@ return ProxiedObservableFactory;

var vivisect = function (initialState) { return new ProxiedObservableFactory()
.create(initialState); };
/**
* @summary 'Vivisect' an object - render the object evented by
* proxying it through a subscribable interface
*
* @param initialState
*
* @public
*/
var vivisect = function (initialState) {
if (isObject(initialState) || Array.isArray(initialState)) {
return ProxiedObservableFactory.create(initialState);
}
throw VxException.create(new VxException({
reason: 'invalid initial state type'
}));
};
export { vivisect };

@@ -31,4 +31,4 @@

/* global Reflect, Promise */
var _extendStatics = function extendStatics(d, b) {
_extendStatics = Object.setPrototypeOf || {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf || {
__proto__: []

@@ -38,8 +38,6 @@ } instanceof Array && function (d, b) {

} || function (d, b) {
for (var p in b) {
if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
}
for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
};
return _extendStatics(d, b);
return extendStatics(d, b);
};

@@ -49,5 +47,4 @@

if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
_extendStatics(d, b);
function __() {

@@ -69,6 +66,8 @@ this.constructor = d;

var unboundedSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundedSlice);
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
/**
* @summary Shallow copy an object or array
*
* @internal
*/

@@ -83,12 +82,12 @@ function shallowCopy(base) {

var key = keys[i];
var desc = descriptors[key];
if (!desc.writable) {
desc.writable = true;
desc.configurable = true;
var descriptor = descriptors[key];
if (!descriptor.writable) {
descriptor.writable = true;
descriptor.configurable = true;
}
if (desc.get || desc.set) {
if (descriptor.get || descriptor.set) {
descriptors[key] = {
configurable: true,
writable: !!desc.set,
enumerable: desc.enumerable,
writable: !!descriptor.set,
enumerable: descriptor.enumerable,
value: base[key]

@@ -102,5 +101,6 @@ };

* @summary Define a non-configurable function property `value` with name `name` on a given object `context`
* @param {VxState} context The object on which the property will be defined
* @param {string} name The name of the property
* @param {Function} value The value of the function property
* @param name The name of the property
* @param value The value of the function property
*
* @internal
*/

@@ -118,10 +118,10 @@ function defineNonConfigurableProp(context, name, value) {

* and whether a given property exists on that array's prototype
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/
function isArrayProto(target, prop) {
return Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype)
.includes(prop);
return (Array.isArray(target) &&
Object.getOwnPropertyNames(Array.prototype).includes(prop));
}

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

* and whether it is out of bounds relative to a given target
* @param {VxState} target
* @param {string|symbol} prop
* @returns {boolean}
* @param target
* @param prop
*
* @internal
*/

@@ -140,3 +141,3 @@ function isArrayPropOutOfBounds(target, prop) {

return false;
return Array.isArray(target) && (maybeIdx > (target.length - 1));
return Array.isArray(target) && maybeIdx > target.length - 1;
}

@@ -146,2 +147,4 @@

* @summary Base implementation model for extended errors
*
* @internal
*/

@@ -162,2 +165,4 @@ var BaseVxError = /** @class */ (function (_super) {

* Base implementation for errors
*
* @internal
*/

@@ -175,2 +180,4 @@ var VxError = /** @class */ (function (_super) {

* @summary Exception metadata builder
*
* @internal
*/

@@ -185,4 +192,3 @@ var VxException = /** @class */ (function () {

* @summary Build an error object with the given exception metadata instance
* @param {VxException} instance
* @returns {VxError}
* @param instance
*/

@@ -194,3 +200,2 @@ VxException.create = function (instance) {

* @summary Serialize the source metadata into a string
* @returns {string}
*/

@@ -201,10 +206,9 @@ VxException.prototype.serializeSource = function () {

var _a = this.source, filename = _a.filename, lineno = _a.lineno;
return "at " + filename + ", Ln " + lineno;
return " at " + filename + ", Ln " + lineno;
};
/**
* @summary Serialize the exception metadata into a string
* @returns {string}
*/
VxException.prototype.serialize = function () {
return this.reason + " " + this.serializeSource();
return "" + this.reason + this.serializeSource();
};

@@ -215,105 +219,51 @@ return VxException;

/**
* @summary Validate a provided event handler name, value
* @param {string} eventName
* @param {Function} handler
* @see https://github.com/microsoft/TypeScript/issues/26916
*/
function validateEventHandler(eventName, handler) {
if (!(eventName in this.handlerStore)) {
/**
* @summary Validate a provided event handler
* @param handler
*
* @internal
*/
function validateEventHandler(handler) {
if (typeof handler !== 'function') {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
reason: 'The provided event handler must be a function'
}));
}
else if (typeof handler !== 'function') {
}
/**
* @summary Validate a provided event name
* @param eventName
* @param validEvents - a list of possible valid event names
*
* @internal
*/
function validateEventName(eventName, validEvents) {
if (typeof eventName !== 'string') {
throw VxException.create(new VxException({
reason: 'The provided event handler must be a function'
reason: "Event name must be a string"
}));
}
if (!validEvents.includes(eventName)) {
throw VxException.create(new VxException({
reason: "An unknown event name '" + eventName + "' was provided; there are no subscribable events matching this identifier"
}));
}
}
/**
* @summary Evaluate whether `testValue` is a plain object
* @param testValue
*
* @internal
*/
var isObject = function (testValue) {
return {}.toString.call(testValue) == '[object Object]';
};
var VX_EVENT_TYPE;
(function (VX_EVENT_TYPE) {
VX_EVENT_TYPE["ADD"] = "add";
VX_EVENT_TYPE["DEL"] = "del";
VX_EVENT_TYPE["SET"] = "set";
VX_EVENT_TYPE["BATCHED"] = "batched";
})(VX_EVENT_TYPE || (VX_EVENT_TYPE = {}));
var VX_LISTENER_INTERNALS;
(function (VX_LISTENER_INTERNALS) {
VX_LISTENER_INTERNALS["ADD"] = "addEventListener";
VX_LISTENER_INTERNALS["REM"] = "removeEventListener";
})(VX_LISTENER_INTERNALS || (VX_LISTENER_INTERNALS = {}));
/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
* @summary Construct a done committal function
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
var _a;
/**
* Event-correlated handlers; below are defaults
* @property {VxEventHandlerStore}
*/
this.handlerStore = (_a = {},
_a[VX_EVENT_TYPE.ADD] = new Set(),
_a[VX_EVENT_TYPE.DEL] = new Set(),
_a[VX_EVENT_TYPE.SET] = new Set(),
_a[VX_EVENT_TYPE.BATCHED] = new Set(),
_a);
this.internals = __spreadArray([], Object.values(VX_LISTENER_INTERNALS));
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param {string|symbol} prop The property presently being accessed
* @returns {boolean}
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `addEventListener`, `removeEventListener` on the proxied object
* @param context The context (i.e. `this` instance) of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineListeners = function (context) {
var _this = this;
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.ADD, function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventHandler.call(_this, eventName, handler);
_this.handlerStore[eventName]
.add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, VX_LISTENER_INTERNALS.REM, function (eventName, handler) {
validateEventHandler.call(_this, eventName, handler);
var handlers = _this.handlerStore[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param {object} event An object containing data about the event
* @param {object} context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, context, done) {
this.handlerStore[event.type]
.forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler.call(context, event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
var DoneFunctionBuilder = function (ret) {

@@ -327,4 +277,10 @@ var done = function (commit) {

var eventedArrayPrototypeResolver = function (target, prop) {
var _this = this;
/**
* @summary Define evented analogs on a proxied array prototype
* @param target
* @param prop
*
* @internal
*/
function eventedArrayPrototypeResolver(context, target, prop) {
var ogMethod = target[prop];

@@ -340,8 +296,10 @@ return function () {

var ret = nextState.shift();
var done = DoneFunctionBuilder(function () { return Array.prototype.shift.call(target); });
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
var done = DoneFunctionBuilder(function () {
return Array.prototype.shift.call(target);
});
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -354,7 +312,7 @@ }

});
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
context.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return ret;

@@ -367,10 +325,10 @@ }

var _a;
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args));
return (_a = Array.prototype.unshift).call.apply(_a, __spreadArray([target], args, false));
});
ret = nextState.unshift.apply(nextState, args);
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
}

@@ -382,7 +340,7 @@ return ret;

nextState.reverse();
_this.raiseEvent({
type: VX_EVENT_TYPE.BATCHED,
context.raiseEvent({
type: 'batched',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState;

@@ -393,7 +351,7 @@ }

nextState.push.apply(nextState, args);
_this.raiseEvent({
type: args.length > 1 ? VX_EVENT_TYPE.BATCHED : VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: args.length > 1 ? 'batched' : 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
return nextState.length;

@@ -405,7 +363,7 @@ }

ogMethod.apply(nextState, [arg]);
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
context.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, done);
}, done);
prevState = shallowCopy(target);

@@ -422,18 +380,12 @@ };

};
};
}
var batchedMethods = [
'shift',
'unshift',
'push',
'reverse',
'sort',
'pop'
];
var batchedMethods = ['shift', 'unshift', 'push', 'reverse', 'sort', 'pop'];
/**
* @summary Construct a base proxy handler with an implicit context
* @returns {ProxyHandler<VxState>} Base proxy handler
* @returns {ProxyHandler<?>} Base proxy handler
*
* @internal
*/
function RootHandlerFactory() {
var _this = this;
function RootHandlerFactory(base) {
var rootHandler = {

@@ -449,3 +401,3 @@ get: function (target, prop, recv) {

if (Array.isArray(target) && batchedMethods.includes(prop)) {
return eventedArrayPrototypeResolver.call(_this, target, prop);
return eventedArrayPrototypeResolver(base, target, prop);
}

@@ -462,3 +414,3 @@ // we use reflection to mitigate violation of Proxy invariants, as described in the specification here:

set: function (target, prop, value) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -471,15 +423,16 @@ }

var ret = Reflect.set(nextState, prop, value);
var done = DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); });
if (!(prop in prevState) || isArrayPropOutOfBounds(prevState, prop)) {
_this.raiseEvent({
type: VX_EVENT_TYPE.ADD,
base.raiseEvent({
type: 'add',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}
else {
_this.raiseEvent({
type: VX_EVENT_TYPE.SET,
base.raiseEvent({
type: 'set',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.set(target, prop, value); }));
}, done);
}

@@ -489,3 +442,3 @@ return ret;

deleteProperty: function (target, prop) {
if (!_this.isConfigurableProp(prop)) {
if (!base.isConfigurableProp(prop)) {
return false;

@@ -495,9 +448,12 @@ }

var ret = true;
// tested via public API
// istanbul ignore next
if (Array.isArray(nextState)) {
nextState.splice(Number(prop), 1);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
var numericProp_1 = Number(prop);
nextState.splice(numericProp_1, 1);
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return target.splice(Number(prop), 1); }));
}, DoneFunctionBuilder(function () { return target.splice(numericProp_1, 1); }));
return ret;

@@ -507,9 +463,10 @@ }

Reflect.deleteProperty(nextState, prop);
_this.raiseEvent({
type: VX_EVENT_TYPE.DEL,
base.raiseEvent({
type: 'del',
prevState: prevState,
nextState: nextState
}, _this, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
}, DoneFunctionBuilder(function () { return Reflect.deleteProperty(target, prop); }));
return ret;
}
// istanbul ignore next
return ret;

@@ -521,13 +478,99 @@ }

/**
* Implements base state and shared functionality for a Vivisector observable
* @class BaseObservableFactory
*
* @internal
*/
var BaseObservableFactory = /** @class */ (function () {
function BaseObservableFactory() {
/**
* Event-correlated handlers; below are defaults
*/
this.observers = {
add: new Set(),
del: new Set(),
set: new Set(),
batched: new Set()
};
this.internals = ['subscribe', 'unsubscribe'];
}
/**
* @summary Evaluates whether the given property is marked as non-configurable
* @param prop The property presently being accessed
*/
BaseObservableFactory.prototype.isConfigurableProp = function (prop) {
// see -> https://github.com/microsoft/TypeScript/issues/26255
// btw, this is where TypeScript's bizarre `Array.prototype.includes` approach could screw us over
// if I followed TS' way, I may only pass a string to `includes`, which means if we receive a symbol, we'll return false
// which would propagate to the proxy and lead to a invariant violation
return !this.internals.includes(prop);
};
/**
* @summary Programmatically define `subscribe`, `unsubscribe` on the proxied object
* @param context The context of the target object on which the
* aforementioned listeners will be defined
*/
BaseObservableFactory.prototype.defineSubscribers = function (context) {
var _this = this;
defineNonConfigurableProp(context, 'subscribe', function (eventName, handler, _a) {
var _b = _a === void 0 ? {} : _a, _c = _b.alwaysCommit, alwaysCommit = _c === void 0 ? false : _c;
validateEventName(eventName, Object.keys(_this.observers));
validateEventHandler(handler);
_this.observers[eventName].add({ handler: handler, alwaysCommit: alwaysCommit });
return context;
});
defineNonConfigurableProp(context, 'unsubscribe', function (eventName, handler) {
// both validators are tested via the public API
// istanbul ignore next
validateEventName(eventName, Object.keys(_this.observers));
// istanbul ignore next
validateEventHandler(handler);
var handlers = _this.observers[eventName];
handlers.forEach(function (ref) {
if (handler === ref.handler) {
handlers["delete"](ref);
}
});
return context;
});
return context;
};
/**
* @summary Serially invokes each handler of the given event type
* @param event An object containing data about the event
* @param context The `this` value on which to call each instance
*/
BaseObservableFactory.prototype.raiseEvent = function (event, done) {
this.observers[event.type].forEach(function (_a) {
var handler = _a.handler, alwaysCommit = _a.alwaysCommit;
var finalDoneFunction = done;
// tested via public API
// istanbul ignore next
if (alwaysCommit) {
done(true);
finalDoneFunction = function () { };
}
handler(event, finalDoneFunction);
});
};
return BaseObservableFactory;
}());
/**
* @summary Create proxies
*
* @internal
*/
var ProxiedObservableFactory = /** @class */ (function (_super) {
__extends(ProxiedObservableFactory, _super);
function ProxiedObservableFactory() {
var _this = _super.call(this) || this;
_this.rootHandler = RootHandlerFactory
.call(_this);
return _this;
return _super !== null && _super.apply(this, arguments) || this;
}
ProxiedObservableFactory.prototype.create = function (initialState) {
/**
* @summary Root Proxy handler; injects event broadcasts into get|set|delete traps
*/
ProxiedObservableFactory.create = function (initialState) {
var excisedInitialState = shallowCopy(initialState);
return this.defineListeners(new Proxy(excisedInitialState, this.rootHandler));
var instance = new ProxiedObservableFactory();
return instance.defineSubscribers(new Proxy(excisedInitialState, RootHandlerFactory(instance)));
};

@@ -537,4 +580,18 @@ return ProxiedObservableFactory;

var vivisect = function (initialState) { return new ProxiedObservableFactory()
.create(initialState); };
/**
* @summary 'Vivisect' an object - render the object evented by
* proxying it through a subscribable interface
*
* @param initialState
*
* @public
*/
var vivisect = function (initialState) {
if (isObject(initialState) || Array.isArray(initialState)) {
return ProxiedObservableFactory.create(initialState);
}
throw VxException.create(new VxException({
reason: 'invalid initial state type'
}));
};

@@ -541,0 +598,0 @@ exports.vivisect = vivisect;

@@ -21,2 +21,2 @@ /**

PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},t(e,r)};function r(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}function n(e,t,r){if(r||2===arguments.length)for(var n,i=0,o=t.length;i<o;i++)!n&&i in t||(n||(n=Array.prototype.slice.call(t,0,i)),n[i]=t[i]);return e.concat(n||Array.prototype.slice.call(t))}var i=Array.prototype.slice,o=Function.prototype.call.bind(i);function a(e){if(Array.isArray(e))return o(e);for(var t=Object.getOwnPropertyDescriptors(e),r=Reflect.ownKeys(t),n=0;n<r.length;n++){var i=r[n],a=t[i];a.writable||(a.writable=!0,a.configurable=!0),(a.get||a.set)&&(t[i]={configurable:!0,writable:!!a.set,enumerable:a.enumerable,value:e[i]})}return Object.create(Object.getPrototypeOf(e),t)}function u(e,t,r){Object.defineProperty(e,t,{configurable:!1,enumerable:!1,writable:!1,value:r})}var c,s,f=function(e){function t(r){var n=e.call(this,r)||this;return Object.setPrototypeOf(n,t.prototype),n}return r(t,e),t}(function(e){function t(r){var n=e.call(this,r)||this;return Object.setPrototypeOf(n,t.prototype),n}return r(t,e),t}(Error)),l=function(){function e(e){var t=e.reason,r=e.source;this.reason=t,this.source=r}return e.create=function(e){return new f(e.serialize())},e.prototype.serializeSource=function(){if(!this.source)return"";var e=this.source;return"at "+e.filename+", Ln "+e.lineno},e.prototype.serialize=function(){return this.reason+" "+this.serializeSource()},e}();function p(e,t){if(!(e in this.handlerStore))throw l.create(new l({reason:"An unknown event name '"+e+"' was provided; there are no subscribable events matching this identifier"}));if("function"!=typeof t)throw l.create(new l({reason:"The provided event handler must be a function"}))}!function(e){e.ADD="add",e.DEL="del",e.SET="set",e.BATCHED="batched"}(c||(c={})),function(e){e.ADD="addEventListener",e.REM="removeEventListener"}(s||(s={}));var y=function(){function e(){var e;this.handlerStore=((e={})[c.ADD]=new Set,e[c.DEL]=new Set,e[c.SET]=new Set,e[c.BATCHED]=new Set,e),this.internals=n([],Object.values(s))}return e.prototype.isConfigurableProp=function(e){return!this.internals.includes(e)},e.prototype.defineListeners=function(e){var t=this;return u(e,s.ADD,(function(r,n,i){var o=(void 0===i?{}:i).alwaysCommit,a=void 0!==o&&o;return p.call(t,r,n),t.handlerStore[r].add({handler:n,alwaysCommit:a}),e})),u(e,s.REM,(function(r,n){p.call(t,r,n);var i=t.handlerStore[r];return i.forEach((function(e){n===e.handler&&i.delete(e)})),e})),e},e.prototype.raiseEvent=function(e,t,r){this.handlerStore[e.type].forEach((function(n){var i=n.handler,o=n.alwaysCommit,a=r;o&&(r(!0),a=function(){}),i.call(t,e,a)}))},e}(),v=function(e){return function(t){if(t)return e()}},h=function(e,t){var r=this,i=e[t];return function(){for(var o=[],u=0;u<arguments.length;u++)o[u]=arguments[u];var s=a(e),f=a(e);if("shift"==t){var l=s.shift(),p=v((function(){return Array.prototype.shift.call(e)}));return r.raiseEvent({type:c.BATCHED,prevState:f,nextState:s},r,p),l}if("pop"==t){l=s.pop(),p=v((function(){e.length=e.length-1}));return r.raiseEvent({type:c.DEL,prevState:f,nextState:s},r,p),l}if("unshift"==t){l=e.length;if(o.length){p=v((function(){var t;return(t=Array.prototype.unshift).call.apply(t,n([e],o))}));l=s.unshift.apply(s,o),r.raiseEvent({type:c.BATCHED,prevState:f,nextState:s},r,p)}return l}if("reverse"==t){p=v((function(){return e.reverse()}));return s.reverse(),r.raiseEvent({type:c.BATCHED,prevState:f,nextState:s},r,p),s}if("push"==t){p=v((function(){return e.push.apply(e,o)}));return s.push.apply(s,o),r.raiseEvent({type:o.length>1?c.BATCHED:c.ADD,prevState:f,nextState:s},r,p),s.length}if(o.length){for(var y=function(t){var n=v((function(){return i.apply(e,[t])}));i.apply(s,[t]),r.raiseEvent({type:c.ADD,prevState:f,nextState:s},r,n),f=a(e)},h=0,d=o;h<d.length;h++){var b=d[h];y(b)}return s}return i.apply(e,o)}},d=["shift","unshift","push","reverse","sort","pop"];function b(){var e=this,t={get:function(r,n,i){if(Array.isArray(r)&&d.includes(n))return h.call(e,r,n);var o=Reflect.get(r,n,i);return"object"==typeof o?new Proxy(o,t):o},set:function(t,r,n){if(!e.isConfigurableProp(r))return!1;if(function(e,t){return Array.isArray(e)&&Object.getOwnPropertyNames(Array.prototype).includes(t)}(t,r))return Reflect.set(t,r,n);var i=[a(t),a(t)],o=i[0],u=i[1],s=Reflect.set(u,r,n);return!(r in o)||function(e,t){var r=Number(t);return!!Number.isNaN(r)&&Array.isArray(e)&&r>e.length-1}(o,r)?e.raiseEvent({type:c.ADD,prevState:o,nextState:u},e,v((function(){return Reflect.set(t,r,n)}))):e.raiseEvent({type:c.SET,prevState:o,nextState:u},e,v((function(){return Reflect.set(t,r,n)}))),s},deleteProperty:function(t,r){if(!e.isConfigurableProp(r))return!1;var n=[a(t),a(t)],i=n[0],o=n[1],u=!0;return Array.isArray(o)?(o.splice(Number(r),1),e.raiseEvent({type:c.DEL,prevState:i,nextState:o},e,v((function(){return t.splice(Number(r),1)}))),u):r in i?(Reflect.deleteProperty(o,r),e.raiseEvent({type:c.DEL,prevState:i,nextState:o},e,v((function(){return Reflect.deleteProperty(t,r)}))),u):u}};return t}var S=function(e){function t(){var t=e.call(this)||this;return t.rootHandler=b.call(t),t}return r(t,e),t.prototype.create=function(e){var t=a(e);return this.defineListeners(new Proxy(t,this.rootHandler))},t}(y);e.vivisect=function(e){return(new S).create(e)},Object.defineProperty(e,"__esModule",{value:!0})}));
***************************************************************************** */var t=function(e,r){return t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])},t(e,r)};function r(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Class extends value "+String(r)+" is not a constructor or null");function n(){this.constructor=e}t(e,r),e.prototype=null===r?Object.create(r):(n.prototype=r.prototype,new n)}function n(e,t,r){if(r||2===arguments.length)for(var n,i=0,o=t.length;i<o;i++)!n&&i in t||(n||(n=Array.prototype.slice.call(t,0,i)),n[i]=t[i]);return e.concat(n||Array.prototype.slice.call(t))}var i=Array.prototype.slice,o=Function.prototype.call.bind(i);function a(e){if(Array.isArray(e))return o(e);for(var t=Object.getOwnPropertyDescriptors(e),r=Reflect.ownKeys(t),n=0;n<r.length;n++){var i=r[n],a=t[i];a.writable||(a.writable=!0,a.configurable=!0),(a.get||a.set)&&(t[i]={configurable:!0,writable:!!a.set,enumerable:a.enumerable,value:e[i]})}return Object.create(Object.getPrototypeOf(e),t)}function u(e,t,r){Object.defineProperty(e,t,{configurable:!1,enumerable:!1,writable:!1,value:r})}var s=function(e){function t(r){var n=e.call(this,r)||this;return Object.setPrototypeOf(n,t.prototype),n}return r(t,e),t}(function(e){function t(r){var n=e.call(this,r)||this;return Object.setPrototypeOf(n,t.prototype),n}return r(t,e),t}(Error)),c=function(){function e(e){var t=e.reason,r=e.source;this.reason=t,this.source=r}return e.create=function(e){return new s(e.serialize())},e.prototype.serializeSource=function(){if(!this.source)return"";var e=this.source;return" at "+e.filename+", Ln "+e.lineno},e.prototype.serialize=function(){return""+this.reason+this.serializeSource()},e}();function f(e){if("function"!=typeof e)throw c.create(new c({reason:"The provided event handler must be a function"}))}function p(e,t){if("string"!=typeof e)throw c.create(new c({reason:"Event name must be a string"}));if(!t.includes(e))throw c.create(new c({reason:"An unknown event name '"+e+"' was provided; there are no subscribable events matching this identifier"}))}var l=function(e){return function(t){if(t)return e()}};var y=["shift","unshift","push","reverse","sort","pop"];function v(e){var t={get:function(r,i,o){if(Array.isArray(r)&&y.includes(i))return function(e,t,r){var i=t[r];return function(){for(var o=[],u=0;u<arguments.length;u++)o[u]=arguments[u];var s=a(t),c=a(t);if("shift"==r){var f=s.shift(),p=l((function(){return Array.prototype.shift.call(t)}));return e.raiseEvent({type:"batched",prevState:c,nextState:s},p),f}if("pop"==r)return f=s.pop(),p=l((function(){t.length=t.length-1})),e.raiseEvent({type:"del",prevState:c,nextState:s},p),f;if("unshift"==r)return f=t.length,o.length&&(p=l((function(){var e;return(e=Array.prototype.unshift).call.apply(e,n([t],o,!1))})),f=s.unshift.apply(s,o),e.raiseEvent({type:"batched",prevState:c,nextState:s},p)),f;if("reverse"==r)return p=l((function(){return t.reverse()})),s.reverse(),e.raiseEvent({type:"batched",prevState:c,nextState:s},p),s;if("push"==r)return p=l((function(){return t.push.apply(t,o)})),s.push.apply(s,o),e.raiseEvent({type:o.length>1?"batched":"add",prevState:c,nextState:s},p),s.length;if(o.length){for(var y=function(r){var n=l((function(){return i.apply(t,[r])}));i.apply(s,[r]),e.raiseEvent({type:"add",prevState:c,nextState:s},n),c=a(t)},v=0,h=o;v<h.length;v++){y(h[v])}return s}return i.apply(t,o)}}(e,r,i);var u=Reflect.get(r,i,o);return"object"==typeof u?new Proxy(u,t):u},set:function(t,r,n){if(!e.isConfigurableProp(r))return!1;if(function(e,t){return Array.isArray(e)&&Object.getOwnPropertyNames(Array.prototype).includes(t)}(t,r))return Reflect.set(t,r,n);var i=[a(t),a(t)],o=i[0],u=i[1],s=Reflect.set(u,r,n),c=l((function(){return Reflect.set(t,r,n)}));return!(r in o)||function(e,t){var r=Number(t);return!!Number.isNaN(r)&&Array.isArray(e)&&r>e.length-1}(o,r)?e.raiseEvent({type:"add",prevState:o,nextState:u},c):e.raiseEvent({type:"set",prevState:o,nextState:u},c),s},deleteProperty:function(t,r){if(!e.isConfigurableProp(r))return!1;var n=[a(t),a(t)],i=n[0],o=n[1],u=!0;if(Array.isArray(o)){var s=Number(r);return o.splice(s,1),e.raiseEvent({type:"del",prevState:i,nextState:o},l((function(){return t.splice(s,1)}))),u}return r in i?(Reflect.deleteProperty(o,r),e.raiseEvent({type:"del",prevState:i,nextState:o},l((function(){return Reflect.deleteProperty(t,r)}))),u):u}};return t}var h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return r(t,e),t.create=function(e){var r=a(e),n=new t;return n.defineSubscribers(new Proxy(r,v(n)))},t}(function(){function e(){this.observers={add:new Set,del:new Set,set:new Set,batched:new Set},this.internals=["subscribe","unsubscribe"]}return e.prototype.isConfigurableProp=function(e){return!this.internals.includes(e)},e.prototype.defineSubscribers=function(e){var t=this;return u(e,"subscribe",(function(r,n,i){var o=(void 0===i?{}:i).alwaysCommit,a=void 0!==o&&o;return p(r,Object.keys(t.observers)),f(n),t.observers[r].add({handler:n,alwaysCommit:a}),e})),u(e,"unsubscribe",(function(r,n){p(r,Object.keys(t.observers)),f(n);var i=t.observers[r];return i.forEach((function(e){n===e.handler&&i.delete(e)})),e})),e},e.prototype.raiseEvent=function(e,t){this.observers[e.type].forEach((function(r){var n=r.handler,i=r.alwaysCommit,o=t;i&&(t(!0),o=function(){}),n(e,o)}))},e}());e.vivisect=function(e){if(t=e,"[object Object]"=={}.toString.call(t)||Array.isArray(e))return h.create(e);var t;throw c.create(new c({reason:"invalid initial state type"}))},Object.defineProperty(e,"__esModule",{value:!0})}));
{
"name": "vivisector",
"version": "1.5.1",
"version": "1.6.0",
"description": "subscribe to any object and commit or revert state mutations",

@@ -33,5 +33,4 @@ "keywords": [

"scripts": {
"coverage": "jest --coverage && pnpm clean",
"lint": "eslint --ext .js,.ts,.json --no-fix .",
"test": "jest --bail --passWithNoTests __tests__",
"test": "jest --bail --coverage __tests__",
"test:watch": "jest --watch",

@@ -41,3 +40,2 @@ "prebuild": "pnpm clean",

"clean": "rimraf coverage dist .build",
"coveralls": "jest --coverage && cat ./coverage/lcov.info | coveralls && pnpm clean",
"prerelease": "npm pack && tar -xvzf *.tgz && rimraf package *.tgz",

@@ -52,3 +50,3 @@ "semantic-release": "semantic-release",

"lint-staged": {
"lib/**/*.ts": [
"src/**/*.ts": [
"pnpm lint",

@@ -62,2 +60,3 @@ "pnpm test"

"@babel/preset-env": "7.15.4",
"@babel/preset-typescript": "7.15.0",
"@commitlint/cli": "^13.1.0",

@@ -71,6 +70,5 @@ "@commitlint/config-conventional": "^13.1.0",

"@types/jest": "27.0.1",
"babel-jest": "27.1.0",
"coveralls": "^3.1.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "24.4.0",

@@ -81,2 +79,3 @@ "husky": "7.0.2",

"lint-staged": "11.1.2",
"prettier": "2.4.1",
"rimraf": "^3.0.2",

@@ -87,5 +86,4 @@ "rollup": "2.56.3",

"semantic-release": "^17.4.7",
"ts-jest": "27.0.5",
"tslib": "2.3.1",
"typescript": "4.3.5"
"typescript": "4.4.4"
},

@@ -92,0 +90,0 @@ "config": {

![Vivisector Logo](/docs/vx.png)
# Vivisector | Subscribe to Any Object ✂️
# Vivisector | Convert any object into an evented, reactive state machine ✂️

@@ -39,3 +39,3 @@ [![Build Status](https://travis-ci.com/MatthewZito/vivisector.svg?branch=master)](https://travis-ci.com/MatthewZito/vivisector)

})
.addEventListener('set', ({ prevState, nextState, done }) => {
.subscribe('set', ({ prevState, nextState, done }) => {
if (!isValidEmail(nextState.email)) {

@@ -121,3 +121,3 @@ emitErrorMessage();

// every time an item is added to `users`, we want to invoke `logAdditions`
users.addEventListener('add', logAdditions, { alwaysCommit: true });
users.subscribe('add', logAdditions, { alwaysCommit: true });

@@ -140,12 +140,12 @@ // let's bring someone fictional into the mix

Event handlers are registered by calling `addEventListener`. This method will exist on every `vivisected` object:
Event handlers are registered by calling `subscribe`. This method will exist on every `vivisected` object:
```js
users.addEventListener(eventType, eventHandler, options);
users.subscribe(eventType, eventHandler, options);
```
And when we're done, we can remove the handler by passing a reference to it into the `removeEventListener` method:
And when we're done, we can remove the handler by passing a reference to it into the `unsubscribe` method:
```js
users.removeEventListener(eventType, eventHandlerRef);
users.unsubscribe(eventType, eventHandlerRef);
```

@@ -170,4 +170,2 @@

**Type (TypeScript only)** `VX_LISTENER_INTERNALS.ADD`
**Note:** Operations such as `Array.prototype.push` are considered `batched` events if provided more than a single argument

@@ -188,4 +186,2 @@

**Type (TypeScript only)** `VX_LISTENER_INTERNALS.SET`
#### del

@@ -204,4 +200,2 @@

**Type (TypeScript only)** `VX_LISTENER_INTERNALS.DEL`
#### batched

@@ -220,4 +214,2 @@

**Type (TypeScript only)** `VX_LISTENER_INTERNALS.BATCHED`
### <a name="methods"></a> Methods

@@ -227,3 +219,3 @@

#### addEventListener (eventName: VX_EVENT_TYPE, handler: VxEventHandler, { alwaysCommit = false }: { alwaysCommit?: boolean }): VxEventedObject
#### subscribe (eventName: ISubscriptionEvent, handler: ISubscriptionCallback, opts?: ISubscriptionOpts) => IVivisectorApi

@@ -248,3 +240,3 @@ Bind the callback `handler` to fire whenever an event of `eventName` has been triggered.

const languages = vivisect(['C', 'Go']).addEventListener('add', logMsg);
const languages = vivisect(['C', 'Go']).subscribe('add', logMsg);

@@ -255,3 +247,3 @@ languages.push('JavaScript');

#### removeEventListener (eventName: VX_EVENT_TYPE, handler: VxEventHandler): void
#### unsubscribe (eventName: ISubscriptionEvent, handler: ISubscriptionCallback, opts?: ISubscriptionOpts) => IVivisectorApi

@@ -272,4 +264,4 @@ Remove an existing callback from the respective event-type to which it has been registered.

const queens = vivisect(['RuPaul', 'Alaska'])
.addEventListener('add', logMsg, { alwaysCommit: true })
.removeEventListener('add', logMsg);
.subscribe('add', logMsg, { alwaysCommit: true })
.unsubscribe('add', logMsg);

@@ -276,0 +268,0 @@ queens.push('Bianca Del Rio');

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc