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

@politie/sherlock

Package Overview
Dependencies
Maintainers
7
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@politie/sherlock - npm Package Compare versions

Comparing version 1.0.0-beta.4 to 1.0.0

6

extras/static-boolean-funcs.d.ts

@@ -7,3 +7,3 @@ import { Derivable } from '../derivable';

*/
export declare const and: <V>(...args: (V | Derivable<V>)[]) => Derivable<V>;
export declare const and: <V>(...args: (V | Derivable<V>)[]) => Derivable<NonNullable<V>>;
/**

@@ -14,3 +14,3 @@ * Performs JavaScript `||` operation on the provided arguments after unpacking.

*/
export declare const or: <V>(...args: (V | Derivable<V>)[]) => Derivable<V>;
export declare const or: <V>(...args: (V | Derivable<V>)[]) => Derivable<NonNullable<V>>;
/**

@@ -21,2 +21,2 @@ * Returns the first operand that is not `null` or `undefined` after unpacking.

*/
export declare const firstNotNull: <V>(...args: (V | Derivable<V>)[]) => Derivable<V>;
export declare const firstNotNull: <V>(...args: (V | Derivable<V>)[]) => Derivable<NonNullable<V>>;
{
"name": "@politie/sherlock",
"version": "1.0.0-beta.4",
"version": "1.0.0",
"private": false,

@@ -59,9 +59,9 @@ "description": "A reactive programming library for JavaScript applications, built with TypeScript.",

"dependencies": {
"tslib": "^1.8.0"
"tslib": "^1.9.0"
},
"devDependencies": {
"@types/chai": "^4.0.4",
"@types/mocha": "^2.2.44",
"@types/node": "^9.3.0",
"@types/sinon": "^4.1.0",
"@types/chai": "^4.1.3",
"@types/mocha": "^5.2.0",
"@types/node": "^10.0.0",
"@types/sinon": "^4.3.1",
"@types/sinon-chai": "^2.7.29",

@@ -72,21 +72,21 @@ "chai": "^4.1.2",

"immutable": "^3.8.2",
"mocha": "^5.0.0",
"nodemon": "^1.12.1",
"npm-run-all": "^4.1.1",
"nyc": "^11.2.1",
"mocha": "^5.1.1",
"nodemon": "^1.17.3",
"npm-run-all": "^4.1.2",
"nyc": "^11.7.1",
"rimraf": "^2.6.2",
"rollup": "^0.56.2",
"rollup-plugin-commonjs": "^8.2.6",
"rollup-plugin-node-resolve": "^3.0.0",
"rollup": "^0.58.2",
"rollup-plugin-commonjs": "^9.1.2",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-sourcemaps": "^0.4.2",
"rollup-plugin-visualizer": "^0.3.1",
"rxjs": "^5.5.2",
"shelljs": "^0.8.0",
"sinon": "^4.0.2",
"sinon-chai": "^2.14.0",
"ts-node": "^5.0.0",
"tsconfig-paths": "^3.1.1",
"tslint": "^5.8.0",
"typescript": "~2.7.1"
"rollup-plugin-visualizer": "^0.6.0",
"rxjs": "^5.4.0 || ^6.0.0",
"shelljs": "^0.8.1",
"sinon": "^5.0.1",
"sinon-chai": "^3.0.0",
"ts-node": "^6.0.2",
"tsconfig-paths": "^3.3.1",
"tslint": "^5.9.1",
"typescript": "^2.8.3"
}
}
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.sherlock = {})));
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.sherlock = {})));
}(this, (function (exports) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
var __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
return t;
};
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
var currentRecording;
/**
* Will record all dependencies that were touched until {@link stopRecordingObservations} is called. Changes
* {@link TrackedObserver#dependencies} during the recording, so both the number of element and the order of elements
* cannot be relied upon.
*
* Recordings can be nested, this recording will replace the current recording if applicable. After stopping this recording
* the previous recording will become active again.
*
* @param observer the observer that is interested in its dependencies
*/
function startRecordingObservations(observer) {
// Check for cyclic observer dependencies (which is only possible when using impure functions in Derivables)
// we do not support that.
var r = currentRecording;
while (r) {
if (r.observer === observer) {
throw new Error('cyclic dependency between derivables detected');
var currentRecording;
/**
* Will record all dependencies that were touched until {@link stopRecordingObservations} is called. Changes
* {@link TrackedObserver#dependencies} during the recording, so both the number of element and the order of elements
* cannot be relied upon.
*
* Recordings can be nested, this recording will replace the current recording if applicable. After stopping this recording
* the previous recording will become active again.
*
* @param observer the observer that is interested in its dependencies
*/
function startRecordingObservations(observer) {
// Check for cyclic observer dependencies (which is only possible when using impure functions in Derivables)
// we do not support that.
var r = currentRecording;
while (r) {
if (r.observer === observer) {
throw new Error('cyclic dependency between derivables detected');
}
r = r.previousRecording;
}
r = r.previousRecording;
currentRecording = { observer: observer, confirmed: 0, previousRecording: currentRecording };
}
currentRecording = { observer: observer, confirmed: 0, previousRecording: currentRecording };
}
/**
* Stops the current recording and returns to the previous recording if applicable. Will remove any dependency from the
* {@link TrackedObserver#dependencies} array that was not touched since the call to {@link startRecordingObservations}.
* It will also update {@link TrackedObserver#dependencyVersions} and call disconnect on any dependency that can be disconnected
* if it is not observed anymore.
*/
function stopRecordingObservations() {
var recording = currentRecording;
if (!recording) {
throw new Error('No active recording!');
/**
* Stops the current recording and returns to the previous recording if applicable. Will remove any dependency from the
* {@link TrackedObserver#dependencies} array that was not touched since the call to {@link startRecordingObservations}.
* It will also update {@link TrackedObserver#dependencyVersions} and call disconnect on any dependency that can be disconnected
* if it is not observed anymore.
*/
function stopRecordingObservations() {
var recording = currentRecording;
if (!recording) {
throw new Error('No active recording!');
}
currentRecording = recording.previousRecording;
var confirmed = recording.confirmed, observer = recording.observer;
var dependencies = observer.dependencies, dependencyVersions = observer.dependencyVersions;
// Any previous dependency that was not confirmed during the recording can be removed now.
for (var i = confirmed, n = dependencies.length; i < n; i++) {
removeObserver(dependencies[i], observer);
}
dependencies.length = confirmed;
for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) {
var dep = dependencies_1[_i];
dependencyVersions[dep.id] = dep.version;
}
}
currentRecording = recording.previousRecording;
var confirmed = recording.confirmed, observer = recording.observer;
var dependencies = observer.dependencies, dependencyVersions = observer.dependencyVersions;
// Any previous dependency that was not confirmed during the recording can be removed now.
for (var i = confirmed, n = dependencies.length; i < n; i++) {
removeObserver(dependencies[i], observer);
/**
* Returns true iff we are currently recording dependencies.
*/
function isRecordingObservations() {
return !!currentRecording;
}
dependencies.length = confirmed;
for (var _i = 0, dependencies_1 = dependencies; _i < dependencies_1.length; _i++) {
var dep = dependencies_1[_i];
dependencyVersions[dep.id] = dep.version;
}
}
/**
* Returns true iff we are currently recording dependencies.
*/
function isRecordingObservations() {
return !!currentRecording;
}
/**
* Records in the current recording (if applicable) that the given `dependency` was observed.
*
* @param dependency the observable that is being observed
*/
function recordObservation(dependency) {
if (!currentRecording) {
// Not currently recording observations, nevermind...
return;
}
var observer = currentRecording.observer;
var dependencies = observer.dependencies;
// Invariants:
// - dependencies[0..currentRecording.confirmed) have been recorded (confirmed) as dependencies
// - dependencies[currentRecording.confirmed..n) have not yet been recorded (confirmed)
if (dependencies[currentRecording.confirmed] === dependency) {
// This is the expected branch almost everytime we rerecord a derivation. The dependencies are often encountered in the
// same order as before. So we found our dependency at dependencies[currentRecording.confirmed]. We can keep our invariant and
// include our latest observation by incrementing the confirmed counter. Our observer is already registered at this
// dependency because of last time.
currentRecording.confirmed++;
}
else {
// This branch means this is either the first recording, this dependency is new, or the dependencies are out of order
// compared to last time.
var index = dependencies.indexOf(dependency);
if (index < 0) {
// dependency not yet present in dependencies array. This means we have to register the observer at
// the dependency and add the dependency to the observer (both ways).
dependency.observers.push(observer);
if (currentRecording.confirmed === dependencies.length) {
// We don't have to reorder dependencies, because it is empty to the right of currentRecording.confirmed.
dependencies.push(dependency);
/**
* Records in the current recording (if applicable) that the given `dependency` was observed.
*
* @param dependency the observable that is being observed
*/
function recordObservation(dependency) {
if (!currentRecording) {
// Not currently recording observations, nevermind...
return;
}
var observer = currentRecording.observer;
var dependencies = observer.dependencies;
// Invariants:
// - dependencies[0..currentRecording.confirmed) have been recorded (confirmed) as dependencies
// - dependencies[currentRecording.confirmed..n) have not yet been recorded (confirmed)
if (dependencies[currentRecording.confirmed] === dependency) {
// This is the expected branch almost everytime we rerecord a derivation. The dependencies are often encountered in the
// same order as before. So we found our dependency at dependencies[currentRecording.confirmed]. We can keep our invariant and
// include our latest observation by incrementing the confirmed counter. Our observer is already registered at this
// dependency because of last time.
currentRecording.confirmed++;
}
else {
// This branch means this is either the first recording, this dependency is new, or the dependencies are out of order
// compared to last time.
var index = dependencies.indexOf(dependency);
if (index < 0) {
// dependency not yet present in dependencies array. This means we have to register the observer at
// the dependency and add the dependency to the observer (both ways).
dependency.observers.push(observer);
if (currentRecording.confirmed === dependencies.length) {
// We don't have to reorder dependencies, because it is empty to the right of currentRecording.confirmed.
dependencies.push(dependency);
}
else {
// Simple way to keep the invariant, move the current item to the end and
// insert the new dependency in the current position.
dependencies.push(dependencies[currentRecording.confirmed]);
dependencies[currentRecording.confirmed] = dependency;
}
// dependencies[0..currentRecording.confirmed) are dependencies and dependencies[currentRecording.confirmed] is a dependency
currentRecording.confirmed++;
// dependencies[0..currentRecording.confirmed) are dependencies
}
else {
// Simple way to keep the invariant, move the current item to the end and
// insert the new dependency in the current position.
dependencies.push(dependencies[currentRecording.confirmed]);
else if (index > currentRecording.confirmed) {
// dependency is present in dependencies, but we were not expecting it yet, swap places
dependencies[index] = dependencies[currentRecording.confirmed];
dependencies[currentRecording.confirmed] = dependency;
currentRecording.confirmed++;
}
// dependencies[0..currentRecording.confirmed) are dependencies and dependencies[currentRecording.confirmed] is a dependency
currentRecording.confirmed++;
// dependencies[0..currentRecording.confirmed) are dependencies
// else: index >= 0 && index < currentRecording.confirmed, i.e. already seen before and already confirmed. Do nothing.
}
else if (index > currentRecording.confirmed) {
// dependency is present in dependencies, but we were not expecting it yet, swap places
dependencies[index] = dependencies[currentRecording.confirmed];
dependencies[currentRecording.confirmed] = dependency;
currentRecording.confirmed++;
// Postcondition:
// - dependency in dependencies[0..currentRecording.confirmed)
}
/**
* Removes a single observer from the registered observers of the observable. Will error if the observer is not known.
* If the observable has no observers left and can be disconnected it will be disconnected.
*
* @param observable the observable from which to remove the registered observer
* @param observer the observer that has to be removed
*/
function removeObserver(observable, observer) {
var observers = observable.observers;
var i = observers.indexOf(observer);
// istanbul ignore if: should never happen!
if (i < 0) {
throw new Error('Inconsistent state!');
}
// else: index >= 0 && index < currentRecording.confirmed, i.e. already seen before and already confirmed. Do nothing.
observers.splice(i, 1);
// If the dependency is itself another observer and is not observed anymore, we should disconnect it.
if (observers.length === 0 && canBeDisconnected(observable)) {
observable.disconnect();
}
}
// Postcondition:
// - dependency in dependencies[0..currentRecording.confirmed)
}
/**
* Removes a single observer from the registered observers of the observable. Will error if the observer is not known.
* If the observable has no observers left and can be disconnected it will be disconnected.
*
* @param observable the observable from which to remove the registered observer
* @param observer the observer that has to be removed
*/
function removeObserver(observable, observer) {
var observers = observable.observers;
var i = observers.indexOf(observer);
// istanbul ignore if: should never happen!
if (i < 0) {
throw new Error('Inconsistent state!');
function canBeDisconnected(obj) {
return obj && typeof obj.disconnect === 'function';
}
observers.splice(i, 1);
// If the dependency is itself another observer and is not observed anymore, we should disconnect it.
if (observers.length === 0 && canBeDisconnected(observable)) {
observable.disconnect();
}
}
function canBeDisconnected(obj) {
return obj && typeof obj.disconnect === 'function';
}
var currentTransaction;
/**
* Returns true iff we are currently in a transaction.
*/
function inTransaction() {
return !!currentTransaction;
}
/**
* Processes a changed atom. The observertree starting at this atom will be marked stale. When not inside a transaction all
* reactors in this tree will also get a chance to fire (otherwise they will be remembered and fired later).
*
* @param atom the atom that was changed
* @param oldValue the previous value of the atom
* @param oldVersion the previous version number of the atom
*/
function processChangedAtom(atom, oldValue, oldVersion) {
if (currentTransaction) {
processChangedAtomInTransaction(currentTransaction, atom, oldValue, oldVersion);
var currentTransaction;
/**
* Returns true iff we are currently in a transaction.
*/
function inTransaction() {
return !!currentTransaction;
}
else {
var reactors = [];
markObservers(atom, reactors);
reactIfNeeded(reactors);
/**
* Processes a changed atom. The observertree starting at this atom will be marked stale. When not inside a transaction all
* reactors in this tree will also get a chance to fire (otherwise they will be remembered and fired later).
*
* @param atom the atom that was changed
* @param oldValue the previous value of the atom
* @param oldVersion the previous version number of the atom
*/
function processChangedAtom(atom, oldValue, oldVersion) {
if (currentTransaction) {
processChangedAtomInTransaction(currentTransaction, atom, oldValue, oldVersion);
}
else {
var reactors = [];
markObservers(atom, reactors);
reactIfNeeded(reactors);
}
}
}
function markObservers(changedAtom, reactorSink) {
for (var _i = 0, _a = changedAtom.observers; _i < _a.length; _i++) {
var observer = _a[_i];
observer.mark(reactorSink);
function markObservers(changedAtom, reactorSink) {
for (var _i = 0, _a = changedAtom.observers; _i < _a.length; _i++) {
var observer = _a[_i];
observer.mark(reactorSink);
}
}
}
function reactIfNeeded(reactors) {
for (var _i = 0, reactors_1 = reactors; _i < reactors_1.length; _i++) {
var reactor = reactors_1[_i];
reactor.reactIfNeeded();
function reactIfNeeded(reactors) {
for (var _i = 0, reactors_1 = reactors; _i < reactors_1.length; _i++) {
var reactor = reactors_1[_i];
reactor.reactIfNeeded();
}
}
}
/**
* Runs the given function inside a new transaction. Transactions can be nested. If a transaction is already running, this will nest
* the new transaction inside the other. If the function completes normally it will commit the transaction, on a thrown Error it will
* rollback. Returns the return value or rethrows the Error. Only when the outermost transaction completes normally all pending
* reactions will fire, otherwise all atoms will be restored to their state before the transaction started.
*
* @param f the function to run in a transaction
*/
function transact(f) {
beginTransaction();
var result;
try {
result = f();
/**
* Runs the given function inside a new transaction. Transactions can be nested. If a transaction is already running, this will nest
* the new transaction inside the other. If the function completes normally it will commit the transaction, on a thrown Error it will
* rollback. Returns the return value or rethrows the Error. Only when the outermost transaction completes normally all pending
* reactions will fire, otherwise all atoms will be restored to their state before the transaction started.
*
* @param f the function to run in a transaction
*/
function transact(f) {
beginTransaction();
var result;
try {
result = f();
}
catch (e) {
rollbackTransaction();
throw e;
}
commitTransaction();
return result;
}
catch (e) {
rollbackTransaction();
throw e;
/**
* Guarantees that f is called inside transaction, but will not create a new transaction when one is already running.
*
* @param f the function to run in a transaction
*/
function atomically(f) {
if (inTransaction()) {
return f();
}
else {
return transact(f);
}
}
commitTransaction();
return result;
}
/**
* Guarantees that f is called inside transaction, but will not create a new transaction when one is already running.
*
* @param f the function to run in a transaction
*/
function atomically(f) {
if (inTransaction()) {
return f();
function atomic(f) {
if (f) {
return function atomicFunction() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var ctx = this;
return atomically(function () { return f.apply(ctx, args); });
};
}
else {
return function (_target, _propertyKey, descriptor) {
descriptor.value = descriptor.value && atomic(descriptor.value);
};
}
}
else {
return transact(f);
function transaction(f) {
if (f) {
return function transactionFunction() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var ctx = this;
return transact(function () { return f.apply(ctx, args); });
};
}
else {
return function (_target, _propertyKey, descriptor) {
descriptor.value = descriptor.value && transaction(descriptor.value);
};
}
}
}
function atomic(f) {
if (f) {
return function atomicFunction() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var ctx = this;
return atomically(function () { return f.apply(ctx, args); });
function beginTransaction() {
currentTransaction = {
touchedAtoms: [],
oldValues: {},
oldVersions: {},
touchedReactors: [],
parentTransaction: currentTransaction,
};
}
else {
return function (_target, _propertyKey, descriptor) {
descriptor.value = descriptor.value && atomic(descriptor.value);
};
function commitTransaction() {
var ctx = currentTransaction;
// istanbul ignore if: should never happen!
if (!ctx) {
throw new Error('No active transaction!');
}
currentTransaction = ctx.parentTransaction;
if (currentTransaction) {
// Hand over all info to the parent transaction
ctx.touchedAtoms.forEach(function (atom) { return processChangedAtomInTransaction(currentTransaction, atom, ctx.oldValues[atom.id], ctx.oldVersions[atom.id]); });
// Not all reactors might be reached through notifyObservers. When
// all paths between ctx.touchedAtoms and ctx.touchedReactors have
// derivations with in !upToDate state in them, the reactors are not
// added to currentTransaction.touchedReactors, therefore we have to
// do it explicitly here.
(_a = currentTransaction.touchedReactors).push.apply(_a, ctx.touchedReactors);
}
else {
// No parent transaction, so we just committed the outermost transaction, let's react.
reactIfNeeded(ctx.touchedReactors);
}
var _a;
}
}
function transaction(f) {
if (f) {
return function transactionFunction() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var ctx = this;
return transact(function () { return f.apply(ctx, args); });
};
function rollbackTransaction() {
var ctx = currentTransaction;
// istanbul ignore if: should never happen!
if (!ctx) {
throw new Error('No active transaction!');
}
currentTransaction = ctx.parentTransaction;
// Restore the state of all touched atoms.
ctx.touchedAtoms.forEach(function (atom) {
atom.value = ctx.oldValues[atom.id];
atom.version = ctx.oldVersions[atom.id];
markObservers(atom, []);
});
}
else {
return function (_target, _propertyKey, descriptor) {
descriptor.value = descriptor.value && transaction(descriptor.value);
};
function processChangedAtomInTransaction(txn, atom, oldValue, oldVersion) {
markObservers(atom, txn.touchedReactors);
var id = atom.id;
if (!(id in txn.oldValues)) {
txn.touchedAtoms.push(atom);
txn.oldValues[id] = oldValue;
txn.oldVersions[id] = oldVersion;
}
}
}
function beginTransaction() {
currentTransaction = {
touchedAtoms: [],
oldValues: {},
oldVersions: {},
touchedReactors: [],
parentTransaction: currentTransaction,
};
}
function commitTransaction() {
var ctx = currentTransaction;
// istanbul ignore if: should never happen!
if (!ctx) {
throw new Error('No active transaction!');
/**
* Creates a shallow clone of the object with the same prototype chain and working getters and setters.
*
* @param obj the object to clone
*/
function clone(obj) {
if (Array.isArray(obj)) {
// Special support for Array.isArray is needed because Array.isArray checks for array exotic object, which can only be made by
// the Array constructor.
return cloneArray(obj);
}
return Object.create(Object.getPrototypeOf(obj), getOwnPropertyDescriptors(obj));
}
currentTransaction = ctx.parentTransaction;
if (currentTransaction) {
// Hand over all info to the parent transaction
ctx.touchedAtoms.forEach(function (atom) { return processChangedAtomInTransaction(currentTransaction, atom, ctx.oldValues[atom.id], ctx.oldVersions[atom.id]); });
// Not all reactors might be reached through notifyObservers. When
// all paths between ctx.touchedAtoms and ctx.touchedReactors have
// derivations with in !upToDate state in them, the reactors are not
// added to currentTransaction.touchedReactors, therefore we have to
// do it explicitly here.
(_a = currentTransaction.touchedReactors).push.apply(_a, ctx.touchedReactors);
function cloneArray(obj) {
try {
return Object.defineProperties(new obj.constructor(), getOwnPropertyDescriptors(obj));
}
catch (e) {
// istanbul ignore next: for debug purposes
throw Object.assign(new Error('could not construct a clone of the provided Array: ' + (e && e.message)), { jse_cause: e });
}
}
else {
// No parent transaction, so we just committed the outermost transaction, let's react.
reactIfNeeded(ctx.touchedReactors);
// istanbul ignore next: cannot be tested in a modern Node environment
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || getOwnPropertyDescriptorsShim;
function getOwnPropertyDescriptorsShim(obj) {
var properties = {};
for (var _i = 0, _a = ownKeys(obj); _i < _a.length; _i++) {
var prop = _a[_i];
properties[prop] = Object.getOwnPropertyDescriptor(obj, prop);
}
return properties;
}
var _a;
}
function rollbackTransaction() {
var ctx = currentTransaction;
// istanbul ignore if: should never happen!
if (!ctx) {
throw new Error('No active transaction!');
// istanbul ignore next: cannot be tested in a modern Node environment
var ownKeys = typeof Reflect !== 'undefined' ? Reflect.ownKeys : ownKeysShim;
function ownKeysShim(obj) {
return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
}
currentTransaction = ctx.parentTransaction;
// Restore the state of all touched atoms.
ctx.touchedAtoms.forEach(function (atom) {
atom.value = ctx.oldValues[atom.id];
atom.version = ctx.oldVersions[atom.id];
markObservers(atom, []);
});
}
function processChangedAtomInTransaction(txn, atom, oldValue, oldVersion) {
markObservers(atom, txn.touchedReactors);
var id = atom.id;
if (!(id in txn.oldValues)) {
txn.touchedAtoms.push(atom);
txn.oldValues[id] = oldValue;
txn.oldVersions[id] = oldVersion;
}
}
/**
* Creates a shallow clone of the object with the same prototype chain and working getters and setters.
*
* @param obj the object to clone
*/
function clone(obj) {
if (Array.isArray(obj)) {
// Special support for Array.isArray is needed because Array.isArray checks for array exotic object, which can only be made by
// the Array constructor.
return cloneArray(obj);
/**
* Returns whether the two arguments are either:
* - equal according to JavaScript rules
* - equal immutable objects
* - equal derivables
* - equal derivable proxies
*/
function equals(a, b) {
return Object.is(a, b)
|| hasEqualsMethod(a) && !!a.equals(b);
}
return Object.create(Object.getPrototypeOf(obj), getOwnPropertyDescriptors(obj));
}
function cloneArray(obj) {
try {
return Object.defineProperties(new obj.constructor(), getOwnPropertyDescriptors(obj));
function hasEqualsMethod(obj) {
return obj && typeof obj.equals === 'function';
}
catch (e) {
// istanbul ignore next: for debug purposes
throw Object.assign(new Error('could not construct a clone of the provided Array: ' + (e && e.message)), { jse_cause: e });
/**
* Function to test if an object is a plain object, i.e. is constructed
* by the built-in Object constructor or inherits directly from Object.prototype
* or null. Some built-in objects pass the test, e.g. Math which is a plain object
* and some host or exotic objects may pass also.
*
* @param obj the object to test
*/
function isPlainObject(obj) {
// Basic check for type 'object' that's not null
if (typeof obj !== 'object' || obj == null) {
return false;
}
var proto = Object.getPrototypeOf(obj);
return proto === Object.prototype || proto === null || obj.constructor === Object;
}
}
// istanbul ignore next: cannot be tested in a modern Node environment
var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || getOwnPropertyDescriptorsShim;
function getOwnPropertyDescriptorsShim(obj) {
var properties = {};
for (var _i = 0, _a = ownKeys(obj); _i < _a.length; _i++) {
var prop = _a[_i];
properties[prop] = Object.getOwnPropertyDescriptor(obj, prop);
var nextId = 0;
function uniqueId() {
return nextId++;
}
return properties;
}
// istanbul ignore next: cannot be tested in a modern Node environment
var ownKeys = typeof Reflect !== 'undefined' ? Reflect.ownKeys : ownKeysShim;
function ownKeysShim(obj) {
return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
}
/**
* Returns whether the two arguments are either:
* - equal according to JavaScript rules
* - equal immutable objects
* - equal derivables
* - equal derivable proxies
*/
function equals(a, b) {
return Object.is(a, b)
|| hasEqualsMethod(a) && !!a.equals(b);
}
function hasEqualsMethod(obj) {
return obj && typeof obj.equals === 'function';
}
/**
* Function to test if an object is a plain object, i.e. is constructed
* by the built-in Object constructor or inherits directly from Object.prototype
* or null. Some built-in objects pass the test, e.g. Math which is a plain object
* and some host or exotic objects may pass also.
*
* @param obj the object to test
*/
function isPlainObject(obj) {
// Basic check for type 'object' that's not null
if (typeof obj !== 'object' || obj == null) {
return false;
// Debug mode is implemented in the barrel file, because barrel-files don't support mutable variables.
// The syntax: `export { ... } from '...'` creates a new copy of the variable instead of linking.
var debugMode = false;
function setDebugMode(val) {
debugMode = val;
}
var proto = Object.getPrototypeOf(obj);
return proto === Object.prototype || proto === null || obj.constructor === Object;
}
var nextId = 0;
function uniqueId() {
return nextId++;
}
// Debug mode is implemented in the barrel file, because barrel-files don't support mutable variables.
// The syntax: `export { ... } from '...'` creates a new copy of the variable instead of linking.
var debugMode = false;
function setDebugMode(val) {
debugMode = val;
}
/**
* Derivable is the base class of all derivable state constructs: Atom, Constant, Derivation and Lens.
*/
var Derivable = /** @class */ (function () {
function Derivable() {
/**
* Derivable is the base class of all derivable state constructs: Atom, Constant, Derivation and Lens.
*/
var Derivable = /** @class */ (function () {
function Derivable() {
/**
* The unique ID of this Derivable. Can be used to uniquely identify this Derivable.
*/
this.id = uniqueId();
/**
* @internal
* The observers of this Derivable, do not use this in application code.
*/
this.observers = [];
}
/**
* The unique ID of this Derivable. Can be used to uniquely identify this Derivable.
* Sets this Derivable to autoCache mode. This will cache the value of this Derivable the first time {@link #get} is called every tick
* and release this cache some time after this tick. The value is still guaranteed to be up-to-date with respect to changes in any of
* its dependencies, by using the same mechanism that is used by a reactor. It has a setup cost comparable to starting a reactor every
* first time #get is called per tick. Starting a reactor on a Derivable with an active and up-to-date cache is cheap though.
*/
this.id = uniqueId();
Derivable.prototype.autoCache = function () { return this; };
return Derivable;
}());
/**
* Atom is the basic state holder in a Derivable world. It contains the actual mutable state. In contrast
* with other kinds of derivables that only store immutable (constant) or derived state. Should be constructed
* with the initial state.
*/
var Atom = /** @class */ (function (_super) {
__extends(Atom, _super);
/**
* @internal
* The observers of this Derivable, do not use this in application code.
* Construct a new atom with the provided initial value.
*
* @param value the initial value
*/
this.observers = [];
}
function Atom(value) {
var _this = _super.call(this) || this;
/**
* @internal
* The current version of the state. This number gets incremented every time the state changes. Setting the state to
* an immutable object that is structurally equal to the previous immutable object is not considered a state change.
*/
_this.version = 0;
_this.value = value;
return _this;
}
/**
* Returns the current value of this derivable. Automatically records the use of this derivable when inside a derivation.
*/
Atom.prototype.get = function () {
recordObservation(this);
return this.value;
};
/**
* Sets the value of this atom, fires reactors when expected.
*
* @param newValue the new state
*/
Atom.prototype.set = function (newValue) {
var oldValue = this.value;
if (!equals(newValue, oldValue)) {
this.value = newValue;
processChangedAtom(this, oldValue, this.version++);
}
};
Atom.prototype.swap = function (f) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
this.set(f.apply(void 0, [this.value].concat(args)));
};
return Atom;
}(Derivable));
/**
* Sets this Derivable to autoCache mode. This will cache the value of this Derivable the first time {@link #get} is called every tick
* and release this cache some time after this tick. The value is still guaranteed to be up-to-date with respect to changes in any of
* its dependencies, by using the same mechanism that is used by a reactor. It has a setup cost comparable to starting a reactor every
* first time #get is called per tick. Starting a reactor on a Derivable with an active and up-to-date cache is cheap though.
*/
Derivable.prototype.autoCache = function () { return this; };
return Derivable;
}());
/**
* Atom is the basic state holder in a Derivable world. It contains the actual mutable state. In contrast
* with other kinds of derivables that only store immutable (constant) or derived state. Should be constructed
* with the initial state.
*/
var Atom = /** @class */ (function (_super) {
__extends(Atom, _super);
/**
* @internal
* Construct a new atom with the provided initial value.

@@ -461,74 +505,55 @@ *

*/
function Atom(value) {
var _this = _super.call(this) || this;
/**
* @internal
* The current version of the state. This number gets incremented every time the state changes. Setting the state to
* an immutable object that is structurally equal to the previous immutable object is not considered a state change.
*/
_this.version = 0;
_this.value = value;
return _this;
function atom(value) {
return new Atom(value);
}
/**
* Returns the current value of this derivable. Automatically records the use of this derivable when inside a derivation.
*/
Atom.prototype.get = function () {
recordObservation(this);
return this.value;
function unpack(v) {
return v instanceof Derivable ? v.get() : v;
}
// Implementations:
Derivable.prototype.and = function and(other) {
return this.derive(function (v) { return v && unpack(other); });
};
/**
* Sets the value of this atom, fires reactors when expected.
*
* @param newValue the new state
*/
Atom.prototype.set = function (newValue) {
var oldValue = this.value;
if (!equals(newValue, oldValue)) {
this.value = newValue;
processChangedAtom(this, oldValue, this.version++);
}
Derivable.prototype.or = function or(other) {
return this.derive(function (v) { return v || unpack(other); });
};
Atom.prototype.swap = function (f) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
this.set(f.apply(void 0, [this.value].concat(args)));
Derivable.prototype.not = function not() {
return this.derive(function (v) { return !v; });
};
return Atom;
}(Derivable));
/**
* Construct a new atom with the provided initial value.
*
* @param value the initial value
*/
function atom(value) {
return new Atom(value);
}
Derivable.prototype.is = function is(other) {
return this.derive(equals, other);
};
function unpack(v) {
return v instanceof Derivable ? v.get() : v;
}
// Implementations:
Derivable.prototype.and = function and(other) {
return this.derive(function (v) { return v && unpack(other); });
};
Derivable.prototype.or = function or(other) {
return this.derive(function (v) { return v || unpack(other); });
};
Derivable.prototype.not = function not() {
return this.derive(function (v) { return !v; });
};
Derivable.prototype.is = function is(other) {
return this.derive(equals, other);
};
/**
* Constant represents a basic immutable building block of derivations.
*/
var Constant = /** @class */ (function (_super) {
__extends(Constant, _super);
/**
* Constant represents a basic immutable building block of derivations.
*/
var Constant = /** @class */ (function (_super) {
__extends(Constant, _super);
/**
* Creates a new Constant with the give value.
*
* @param value the immutable value of this Constant
*/
function Constant(
/**
* The readonly value of this Constant.
*/
value) {
var _this = _super.call(this) || this;
_this.value = value;
/**
* @internal
* The version of this Constant, should always stay at 0, because Constants never change.
*/
_this.version = 0;
return _this;
}
/**
* Returns the value of this Constant.
*/
Constant.prototype.get = function () { return this.value; };
return Constant;
}(Derivable));
/**
* Creates a new Constant with the give value.

@@ -538,744 +563,719 @@ *

*/
function Constant(
/**
* The readonly value of this Constant.
*/
value) {
var _this = _super.call(this) || this;
_this.value = value;
/**
* @internal
* The version of this Constant, should always stay at 0, because Constants never change.
*/
_this.version = 0;
return _this;
function constant(value) {
return new Constant(value);
}
/**
* Returns the value of this Constant.
*/
Constant.prototype.get = function () { return this.value; };
return Constant;
}(Derivable));
/**
* Creates a new Constant with the give value.
*
* @param value the immutable value of this Constant
*/
function constant(value) {
return new Constant(value);
}
/**
* Derivation is the implementation of derived state. Automatically tracks other Derivables that are used in the deriver function
* and updates when needed.
*/
var Derivation = /** @class */ (function (_super) {
__extends(Derivation, _super);
/**
* Create a new Derivation using the deriver function.
*
* @param deriver the deriver function
* Derivation is the implementation of derived state. Automatically tracks other Derivables that are used in the deriver function
* and updates when needed.
*/
function Derivation(
/**
* The deriver function that is used to calculate the value of this derivation.
*/
deriver,
/**
* Arguments that will be passed unpacked to the deriver function.
*/
args) {
var _this = _super.call(this) || this;
_this.deriver = deriver;
_this.args = args;
var Derivation = /** @class */ (function (_super) {
__extends(Derivation, _super);
/**
* @internal
* The recorded dependencies of this derivation. Is only used when the derivation is connected (i.e. it is actively used to
* power a reactor, either directly or indirectly with other derivations in between).
* Create a new Derivation using the deriver function.
*
* @param deriver the deriver function
*/
_this.dependencies = [];
function Derivation(
/**
* @internal
* The versions of all dependencies that were used to calculate the currently known value. Is used to determine whether
* the deriver function needs to be called.
* The deriver function that is used to calculate the value of this derivation.
*/
_this.dependencyVersions = {};
deriver,
/**
* Indicates whether the derivation is actively used to power a reactor, either directly or indirectly with other derivations in
* between. Should always be kept up to date in order to prevent memory leaks.
* Arguments that will be passed unpacked to the deriver function.
*/
_this.connected = false;
args) {
var _this = _super.call(this) || this;
_this.deriver = deriver;
_this.args = args;
/**
* @internal
* The recorded dependencies of this derivation. Is only used when the derivation is connected (i.e. it is actively used to
* power a reactor, either directly or indirectly with other derivations in between).
*/
_this.dependencies = [];
/**
* @internal
* The versions of all dependencies that were used to calculate the currently known value. Is used to determine whether
* the deriver function needs to be called.
*/
_this.dependencyVersions = {};
/**
* Indicates whether the derivation is actively used to power a reactor, either directly or indirectly with other derivations in
* between. Should always be kept up to date in order to prevent memory leaks.
*/
_this.connected = false;
/**
* Indicates whether the current cachedValue of this derivation is known to be up to date, or might need an update. Is set to false
* by our dependencies when needed. We should be able to trust `true`.
*/
_this.isUpToDate = false;
/**
* Indicates whether the derivation is in autoCache mode.
*/
_this.autoCacheMode = false;
/**
* Used for debugging. A stack that shows the location where this derivation was created.
*/
_this.stack = debugMode ? Error().stack : undefined;
_this._version = 0;
return _this;
}
Object.defineProperty(Derivation.prototype, "version", {
/**
* @internal
* The current version of the state. This number gets incremented every time the state changes when connected. The version
* is only guaranteed to increase on each change when connected.
*/
get: function () {
if (this.connected && this.shouldUpdate()) {
this.update();
}
return this._version;
},
enumerable: true,
configurable: true
});
/**
* Indicates whether the current cachedValue of this derivation is known to be up to date, or might need an update. Is set to false
* by our dependencies when needed. We should be able to trust `true`.
* Returns the current value of this derivable. Automatically records the use of this derivable when inside a derivation.
*/
_this.isUpToDate = false;
Derivation.prototype.get = function () {
if (this.autoCacheMode && !this.connected) {
// We will connect because of autoCacheMode in next block, after a tick we maybe need to disconnect (if no reactor was started
// in this tick).
this.maybeDisconnectInNextTick();
}
// Are we currently connected or should we connect now? We know we need to connect if an observer is registered or
// isRecordingObservations() returns true (in which case our observer is connecting and therefore recording its dependencies).
if (this.autoCacheMode || this.observers.length || isRecordingObservations()) {
recordObservation(this);
// If we are not connected we should connect (by calling update). Otherwise ask shouldUpdate().
if (!this.connected || this.shouldUpdate()) {
this.update();
}
if (this.cachedError) {
throw this.cachedError;
}
return this.cachedValue;
}
return this.callDeriver();
};
/**
* Indicates whether the derivation is in autoCache mode.
* Ensure the derivable is connected and update the currently cached value of this derivation.
*/
_this.autoCacheMode = false;
Derivation.prototype.update = function () {
startRecordingObservations(this);
var oldValue = this.cachedValue;
try {
var newValue = this.cachedValue = this.callDeriver();
this.cachedError = undefined;
this.isUpToDate = true;
this.connected = true;
if (!equals(newValue, oldValue)) {
this._version++;
}
}
catch (error) {
this.cachedError = error;
}
finally {
stopRecordingObservations();
}
};
/**
* Used for debugging. A stack that shows the location where this derivation was created.
* Call the deriver function without `this` context and log debug stack traces when applicable.
*/
_this.stack = debugMode ? Error().stack : undefined;
_this._version = 0;
return _this;
}
Object.defineProperty(Derivation.prototype, "version", {
Derivation.prototype.callDeriver = function () {
try {
var _a = this, deriver = _a.deriver, args = _a.args;
return args ? deriver.apply(void 0, args.map(unpack)) : deriver();
}
catch (e) {
// tslint:disable-next-line:no-console - console.error is only called when debugMode is set to true
this.stack && console.error(e.message, this.stack);
throw e;
}
};
/**
* Determine if this derivation needs an update (when connected). Compares the recorded dependencyVersions with the
* current actual versions of the dependencies. If there is any mismatch between versions we need to update. Simple.
*/
Derivation.prototype.shouldUpdate = function () {
var _this = this;
// Update the isUpToDate boolean only when it is false.
if (!this.isUpToDate) {
this.isUpToDate = this.dependencies.every(function (obs) { return _this.dependencyVersions[obs.id] === obs.version; });
}
return !this.isUpToDate;
};
/**
* @internal
* The current version of the state. This number gets incremented every time the state changes when connected. The version
* is only guaranteed to increase on each change when connected.
* Mark this derivation and all observers of this derivation as "possible outdated" or "state unknown". If this derivation is already
* in that state, all observers of this derivation are also expected to already be in that state. This invariant should never
* be invalidated. Any reactors we encounter are pushed into the reactorSink.
*/
get: function () {
if (this.connected && this.shouldUpdate()) {
this.update();
Derivation.prototype.mark = function (reactorSink) {
// If we think we're up-to-date our observers might think the same, otherwise, we're good, cause our observers can never
// believe the're up-to-date when any of their dependencies is not up-to-date.
if (this.isUpToDate) {
this.isUpToDate = false;
for (var _i = 0, _a = this.observers; _i < _a.length; _i++) {
var observer = _a[_i];
observer.mark(reactorSink);
}
}
return this._version;
},
enumerable: true,
configurable: true
});
/**
* Returns the current value of this derivable. Automatically records the use of this derivable when inside a derivation.
*/
Derivation.prototype.get = function () {
if (this.autoCacheMode && !this.connected) {
// We will connect because of autoCacheMode in next block, after a tick we maybe need to disconnect (if no reactor was started
// in this tick).
this.maybeDisconnectInNextTick();
}
// Are we currently connected or should we connect now? We know we need to connect if an observer is registered or
// isRecordingObservations() returns true (in which case our observer is connecting and therefore recording its dependencies).
if (this.autoCacheMode || this.observers.length || isRecordingObservations()) {
recordObservation(this);
// If we are not connected we should connect (by calling update). Otherwise ask shouldUpdate().
if (!this.connected || this.shouldUpdate()) {
this.update();
};
/**
* @internal
* Disconnect this derivation. It will disconnect all remaining observers (downstream), stop all reactors that depend on this
* derivation and disconnect all dependencies (upstream) that have no other observers.
*/
Derivation.prototype.disconnect = function () {
if (this.autoCacheMode) {
this.maybeDisconnectInNextTick();
}
if (this.cachedError) {
throw this.cachedError;
else {
this.disconnectNow();
}
return this.cachedValue;
}
return this.callDeriver();
};
/**
* Ensure the derivable is connected and update the currently cached value of this derivation.
*/
Derivation.prototype.update = function () {
startRecordingObservations(this);
var oldValue = this.cachedValue;
try {
var newValue = this.cachedValue = this.callDeriver();
this.cachedError = undefined;
this.isUpToDate = true;
this.connected = true;
if (!equals(newValue, oldValue)) {
this._version++;
};
Derivation.prototype.maybeDisconnectInNextTick = function () {
var _this = this;
setTimeout(function () { return _this.observers.length || _this.disconnectNow(); }, 0);
};
Derivation.prototype.disconnectNow = function () {
this.isUpToDate = false;
this.connected = false;
// Disconnect all observers. When an observer disconnects it removes itself from this array.
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i].disconnect();
}
for (var _i = 0, _a = this.dependencies; _i < _a.length; _i++) {
var dep = _a[_i];
removeObserver(dep, this);
}
this.dependencies.length = 0;
};
Derivation.prototype.autoCache = function () {
this.autoCacheMode = true;
return this;
};
return Derivation;
}(Derivable));
function derivation(f) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
}
catch (error) {
this.cachedError = error;
return new Derivation(f, ps.length ? ps : undefined);
}
Derivable.prototype.derive = function derive(f) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
}
finally {
stopRecordingObservations();
}
return new Derivation(f, [this].concat(ps));
};
/**
* Call the deriver function without `this` context and log debug stack traces when applicable.
*/
Derivation.prototype.callDeriver = function () {
try {
var _a = this, deriver = _a.deriver, args = _a.args;
return args ? deriver.apply(void 0, args.map(unpack)) : deriver();
}
catch (e) {
// tslint:disable-next-line:no-console - console.error is only called when debugMode is set to true
this.stack && console.error(e.message, this.stack);
throw e;
}
Derivable.prototype.pluck = function pluck(key) {
return this.derive(plucker, key);
};
function plucker(obj, key) {
return hasGetter(obj)
? obj.get(key)
: obj[key];
}
function hasGetter(obj) {
return obj && typeof obj.get === 'function';
}
/**
* Determine if this derivation needs an update (when connected). Compares the recorded dependencyVersions with the
* current actual versions of the dependencies. If there is any mismatch between versions we need to update. Simple.
* A Lens is a Derivation that is also settable. It satisfies the Atom interface and can be created using an
* arbitrary get and set function or as a derivation from another Atom or Lens using a deriver (get) and
* transform (set) function. The set function is always called inside a transaction (but will not create a new
* transaction if one is already active) to prevent inconsistent state when an error occurs.
*/
Derivation.prototype.shouldUpdate = function () {
var _this = this;
// Update the isUpToDate boolean only when it is false.
if (!this.isUpToDate) {
this.isUpToDate = this.dependencies.every(function (obs) { return _this.dependencyVersions[obs.id] === obs.version; });
var Lens = /** @class */ (function (_super) {
__extends(Lens, _super);
/**
* Create a new Lens using a get and a set function. The get is used as a normal deriver function
* including the automatic recording of dependencies, the set is used as a sink for new values.
*
* @param param0 the get and set functions
*/
function Lens(_a, args) {
var get = _a.get, set = _a.set;
var _this = _super.call(this, get, args) || this;
_this.setter = set;
return _this;
}
return !this.isUpToDate;
};
/**
* @internal
* Mark this derivation and all observers of this derivation as "possible outdated" or "state unknown". If this derivation is already
* in that state, all observers of this derivation are also expected to already be in that state. This invariant should never
* be invalidated. Any reactors we encounter are pushed into the reactorSink.
*/
Derivation.prototype.mark = function (reactorSink) {
// If we think we're up-to-date our observers might think the same, otherwise, we're good, cause our observers can never
// believe the're up-to-date when any of their dependencies is not up-to-date.
if (this.isUpToDate) {
this.isUpToDate = false;
for (var _i = 0, _a = this.observers; _i < _a.length; _i++) {
var observer = _a[_i];
observer.mark(reactorSink);
/**
* Sets the value of this Lens, the set function provided in the constructor is responsible for maintaining
* the state and should make sure that the next call to `get()` returns the `newValue`.
*
* @param newValue the new state
*/
Lens.prototype.set = function (newValue) {
var _a = this, setter = _a.setter, args = _a.args;
if (args) {
setter.apply(void 0, [newValue].concat(args.map(unpack)));
}
else {
setter(newValue);
}
};
/**
* Swaps the current value of this atom using the provided swap function. Any additional arguments to this function are
* fed to the swap function.
*
* @param f the swap function
*/
Lens.prototype.swap = function (f) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
this.set(f.apply(void 0, [this.get()].concat(args)));
};
/**
* Create a new Lens using the provided deriver (get) and transform (set) functions.
*
* @param param0 the deriver (get) and transform (set) functions
*/
Lens.prototype.lens = function (_a) {
var get = _a.get, set = _a.set;
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
}
var atom$$1 = this;
return new Lens({
get: get,
set: function () { atom$$1.set(set.apply(undefined, arguments)); },
}, [atom$$1].concat(ps));
};
// Locally overridden to return an Atom instead of an ordinary Derivable.
Lens.prototype.pluck = function (key) {
return this.lens({
get: plucker,
set: pluckSetter,
}, key);
};
__decorate([
atomic()
], Lens.prototype, "set", null);
return Lens;
}(Derivation));
function pluckSetter(newValue, object, key) {
if (hasGetter(object)) {
if (hasSetter(object)) {
return object.set(key, newValue);
}
throw new Error('object is readonly');
}
};
/**
* @internal
* Disconnect this derivation. It will disconnect all remaining observers (downstream), stop all reactors that depend on this
* derivation and disconnect all dependencies (upstream) that have no other observers.
*/
Derivation.prototype.disconnect = function () {
if (this.autoCacheMode) {
this.maybeDisconnectInNextTick();
var result = clone(object);
result[key] = newValue;
return result;
}
function hasSetter(obj) {
return typeof obj.set === 'function';
}
function lens(descriptor) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
}
else {
this.disconnectNow();
}
};
Derivation.prototype.maybeDisconnectInNextTick = function () {
var _this = this;
setTimeout(function () { return _this.observers.length || _this.disconnectNow(); }, 0);
};
Derivation.prototype.disconnectNow = function () {
this.isUpToDate = false;
this.connected = false;
// Disconnect all observers. When an observer disconnects it removes itself from this array.
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i].disconnect();
}
for (var _i = 0, _a = this.dependencies; _i < _a.length; _i++) {
var dep = _a[_i];
removeObserver(dep, this);
}
this.dependencies.length = 0;
};
Derivation.prototype.autoCache = function () {
this.autoCacheMode = true;
return this;
};
return Derivation;
}(Derivable));
function derivation(f) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
return new Lens(descriptor, ps.length ? ps : undefined);
}
return new Derivation(f, ps.length ? ps : undefined);
}
Derivable.prototype.derive = function derive(f) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
Atom.prototype.lens = Lens.prototype.lens;
Atom.prototype.pluck = Lens.prototype.pluck;
function lift(f) {
return function () {
var ps = [];
for (var _i = 0; _i < arguments.length; _i++) {
ps[_i] = arguments[_i];
}
return new Derivation(f, ps);
};
}
return new Derivation(f, [this].concat(ps));
};
Derivable.prototype.pluck = function pluck(key) {
return this.derive(plucker, key);
};
function plucker(obj, key) {
return hasGetter(obj)
? obj.get(key)
: obj[key];
}
function hasGetter(obj) {
return obj && typeof obj.get === 'function';
}
/**
* A Lens is a Derivation that is also settable. It satisfies the Atom interface and can be created using an
* arbitrary get and set function or as a derivation from another Atom or Lens using a deriver (get) and
* transform (set) function. The set function is always called inside a transaction (but will not create a new
* transaction if one is already active) to prevent inconsistent state when an error occurs.
*/
var Lens = /** @class */ (function (_super) {
__extends(Lens, _super);
/**
* Create a new Lens using a get and a set function. The get is used as a normal deriver function
* including the automatic recording of dependencies, the set is used as a sink for new values.
*
* @param param0 the get and set functions
*/
function Lens(_a, args) {
var get = _a.get, set = _a.set;
var _this = _super.call(this, get, args) || this;
_this.setter = set;
return _this;
function scan(f, seed) {
var acc = seed;
return function wrapped(value) {
return acc = f.call(this, acc, value);
};
}
/**
* Sets the value of this Lens, the set function provided in the constructor is responsible for maintaining
* the state and should make sure that the next call to `get()` returns the `newValue`.
* Performs JavaScript `&&` operation on the provided arguments after unpacking.
*
* @param newValue the new state
* @method
*/
Lens.prototype.set = function (newValue) {
var _a = this, setter = _a.setter, args = _a.args;
if (args) {
setter.apply(void 0, [newValue].concat(args.map(unpack)));
}
else {
setter(newValue);
}
};
var and = andOrImpl(function (v) { return !v; });
/**
* Swaps the current value of this atom using the provided swap function. Any additional arguments to this function are
* fed to the swap function.
* Performs JavaScript `||` operation on the provided arguments after unpacking.
*
* @param f the swap function
* @method
*/
Lens.prototype.swap = function (f) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
this.set(f.apply(void 0, [this.get()].concat(args)));
};
var or = andOrImpl(function (v) { return !!v; });
/**
* Create a new Lens using the provided deriver (get) and transform (set) functions.
* Returns the first operand that is not `null` or `undefined` after unpacking.
*
* @param param0 the deriver (get) and transform (set) functions
* @method
*/
Lens.prototype.lens = function (_a) {
var get = _a.get, set = _a.set;
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
var firstNotNull = andOrImpl(function (v) { return v != null; });
function andOrImpl(breakOn) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return derivation(function () {
var value;
for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
var arg = args_1[_i];
value = unpack(arg);
if (breakOn(value)) {
break;
}
}
return value;
});
};
}
function struct(obj) {
if (obj instanceof Derivable) {
return obj;
}
var atom$$1 = this;
return new Lens({
get: get,
set: function () { atom$$1.set(set.apply(undefined, arguments)); },
}, [atom$$1].concat(ps));
};
// Locally overridden to return an Atom instead of an ordinary Derivable.
Lens.prototype.pluck = function (key) {
return this.lens({
get: plucker,
set: pluckSetter,
}, key);
};
__decorate([
atomic()
], Lens.prototype, "set", null);
return Lens;
}(Derivation));
function pluckSetter(newValue, object, key) {
if (hasGetter(object)) {
if (hasSetter(object)) {
return object.set(key, newValue);
if (!Array.isArray(obj) && !isPlainObject(obj)) {
throw new Error('"struct" only accepts Derivables, plain Objects and Arrays');
}
throw new Error('object is readonly');
return derivation(deepUnpack, obj);
}
var result = clone(object);
result[key] = newValue;
return result;
}
function hasSetter(obj) {
return typeof obj.set === 'function';
}
function lens(descriptor) {
var ps = [];
for (var _i = 1; _i < arguments.length; _i++) {
ps[_i - 1] = arguments[_i];
function deepUnpack(obj) {
if (obj instanceof Derivable) {
return obj.get();
}
if (Array.isArray(obj)) {
return obj.map(deepUnpack);
}
if (isPlainObject(obj)) {
var result = {};
for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) {
var key = _a[_i];
result[key] = deepUnpack(obj[key]);
}
return result;
}
return obj;
}
return new Lens(descriptor, ps.length ? ps : undefined);
}
Atom.prototype.lens = Lens.prototype.lens;
Atom.prototype.pluck = Lens.prototype.pluck;
function lift(f) {
return function () {
var ps = [];
for (var _i = 0; _i < arguments.length; _i++) {
ps[_i] = arguments[_i];
}
return new Derivation(f, ps);
};
}
function scan(f, seed) {
var acc = seed;
return function wrapped(value) {
return acc = f.call(this, acc, value);
};
}
/**
* Performs JavaScript `&&` operation on the provided arguments after unpacking.
*
* @method
*/
var and = andOrImpl(function (v) { return !v; });
/**
* Performs JavaScript `||` operation on the provided arguments after unpacking.
*
* @method
*/
var or = andOrImpl(function (v) { return !!v; });
/**
* Returns the first operand that is not `null` or `undefined` after unpacking.
*
* @method
*/
var firstNotNull = andOrImpl(function (v) { return v != null; });
function andOrImpl(breakOn) {
return function () {
/**
* A template literal tag to create a string derivation using a template literal.
*
* For example:
*
* ```
* const name$ = atom('Pete');
* const age$ = atom(24);
* const nameAndAge$ = template`${name$} is ${age$} years old`;
* nameAndAge$.get(); // -> Pete is 24 years old
* ```
*
* @param parts the string parts
* @param args the results of the expressions inside the template literal
*/
function template(parts) {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return derivation(function () {
var value;
for (var _i = 0, args_1 = args; _i < args_1.length; _i++) {
var arg = args_1[_i];
value = unpack(arg);
if (breakOn(value)) {
break;
var s = '';
for (var i = 0; i < parts.length; i++) {
s += parts[i];
if (i < args.length) {
s += unpack(args[i]);
}
}
return value;
return s;
});
};
}
}
function struct(obj) {
if (obj instanceof Derivable) {
return obj;
function isAtom(derivable) {
return derivable instanceof Atom || derivable instanceof Lens;
}
if (!Array.isArray(obj) && !isPlainObject(obj)) {
throw new Error('"struct" only accepts Derivables, plain Objects and Arrays');
function isConstant(derivable) {
return derivable instanceof Constant;
}
return derivation(deepUnpack, obj);
}
function deepUnpack(obj) {
if (obj instanceof Derivable) {
return obj.get();
function isDerivable(derivable) {
return derivable instanceof Derivable;
}
if (Array.isArray(obj)) {
return obj.map(deepUnpack);
function isDerivation(derivable) {
return derivable instanceof Derivation;
}
if (isPlainObject(obj)) {
var result = {};
for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) {
var key = _a[_i];
result[key] = deepUnpack(obj[key]);
}
return result;
function isLens(derivable) {
return derivable instanceof Lens;
}
return obj;
}
/**
* A template literal tag to create a string derivation using a template literal.
*
* For example:
*
* ```
* const name$ = atom('Pete');
* const age$ = atom(24);
* const nameAndAge$ = template`${name$} is ${age$} years old`;
* nameAndAge$.get(); // -> Pete is 24 years old
* ```
*
* @param parts the string parts
* @param args the results of the expressions inside the template literal
*/
function template(parts) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
function wrapPreviousState(f, init) {
var oldValue = init;
return function wrapped(newValue) {
var result = f.call(this, newValue, oldValue);
oldValue = newValue;
return result;
};
}
return derivation(function () {
var s = '';
for (var i = 0; i < parts.length; i++) {
s += parts[i];
if (i < args.length) {
s += unpack(args[i]);
}
}
return s;
});
}
function isAtom(derivable) {
return derivable instanceof Atom || derivable instanceof Lens;
}
function isConstant(derivable) {
return derivable instanceof Constant;
}
function isDerivable(derivable) {
return derivable instanceof Derivable;
}
function isDerivation(derivable) {
return derivable instanceof Derivation;
}
function isLens(derivable) {
return derivable instanceof Lens;
}
function wrapPreviousState(f, init) {
var oldValue = init;
return function wrapped(newValue) {
var result = f.call(this, newValue, oldValue);
oldValue = newValue;
return result;
var true$ = constant(true);
var false$ = constant(false);
Derivable.prototype.react = function react(reaction, options) {
return Reactor.create(this, reaction, options);
};
}
var true$ = constant(true);
var false$ = constant(false);
Derivable.prototype.react = function react(reaction, options) {
return Reactor.create(this, reaction, options);
};
/**
* The maximum recursion depth for a single Reactor. Is used to fail faster than JavaScripts "Maximum call stack size
* exceeded" and provide better error messages.
*/
var MAX_REACTION_DEPTH = 100;
var defaultOptions = { from: true$, until: false$, when: true$, once: false, skipFirst: false };
/**
* A Reactor is an observer of a derivable that automatically performs some reaction whenever the derivable changes. Will not
* react to changes when a transaction is active. When all transactions are committed all pending reactors will fire. Note that a
* reactor that is created inside a transaction will still fire the first time (unless skipFirst = true), but will not react
* to changes until the transaction ends.
*/
var Reactor = /** @class */ (function () {
/**
* Create a new instance of Reactor, do not use this directly, use {@link Reactor.create} instead.
*
* @param parent the derivable that should be observed
* @param reaction the reaction that should fire
* The maximum recursion depth for a single Reactor. Is used to fail faster than JavaScripts "Maximum call stack size
* exceeded" and provide better error messages.
*/
function Reactor(
var MAX_REACTION_DEPTH = 100;
var defaultOptions = { from: true$, until: false$, when: true$, once: false, skipFirst: false };
/**
* The derivable that is observed to determine changes.
* A Reactor is an observer of a derivable that automatically performs some reaction whenever the derivable changes. Will not
* react to changes when a transaction is active. When all transactions are committed all pending reactors will fire. Note that a
* reactor that is created inside a transaction will still fire the first time (unless skipFirst = true), but will not react
* to changes until the transaction ends.
*/
parent,
/**
* The reaction that should fire when the derivable changes.
*/
reaction) {
this.parent = parent;
this.reaction = reaction;
var Reactor = /** @class */ (function () {
/**
* When a reactor is active it observes its derivable (parent) and reacts to changes.
* Create a new instance of Reactor, do not use this directly, use {@link Reactor.create} instead.
*
* @param parent the derivable that should be observed
* @param reaction the reaction that should fire
*/
this.active = false;
function Reactor(
/**
* Unique ID for debugging purposes.
* The derivable that is observed to determine changes.
*/
this.id = uniqueId();
parent,
/**
* The current recursion depth of reactions. Can reach a maximum at which point an Error will be thrown.
* The reaction that should fire when the derivable changes.
*/
this.reactionDepth = 0;
reaction) {
this.parent = parent;
this.reaction = reaction;
/**
* When a reactor is active it observes its derivable (parent) and reacts to changes.
*/
this.active = false;
/**
* Unique ID for debugging purposes.
*/
this.id = uniqueId();
/**
* The current recursion depth of reactions. Can reach a maximum at which point an Error will be thrown.
*/
this.reactionDepth = 0;
/**
* Used for debugging. A stack that shows the location where this derivation was created.
*/
this.stack = debugMode ? new Error().stack : undefined;
/**
* The value of the parent when this reactor last reacted. Is used to determine whether it should react again or not.
*/
this.lastValue = {};
}
/**
* Used for debugging. A stack that shows the location where this derivation was created.
* Start this reactor if not already started. Will always run the reaction once with the current value of parent on start.
*/
this.stack = debugMode ? new Error().stack : undefined;
Reactor.prototype.start = function () {
if (this.active) {
return;
}
this.parent.observers.push(this);
this.active = true;
this.reactIfNeeded();
};
/**
* The value of the parent when this reactor last reacted. Is used to determine whether it should react again or not.
* React when active and needed. Does nothing when a reaction is not appropriate.
*/
this.lastValue = {};
}
/**
* Start this reactor if not already started. Will always run the reaction once with the current value of parent on start.
*/
Reactor.prototype.start = function () {
if (this.active) {
return;
}
this.parent.observers.push(this);
this.active = true;
this.reactIfNeeded();
};
/**
* React when active and needed. Does nothing when a reaction is not appropriate.
*/
Reactor.prototype.reactIfNeeded = function () {
if (!this.active) {
return;
}
// Our controller always has first right to react.
if (this.controller) {
this.controller.reactIfNeeded();
}
// Check active again, could have been stopped by controller now.
if (!this.active) {
return;
}
var lastValue = this.lastValue;
var nextValue = this.lastValue = this.parent.get();
if (!equals(lastValue, nextValue)) {
this.react(nextValue);
}
};
/**
* React once. Will call the reaction with the current value of parent and remember the current version of the parent to
* be able to determine when to react next.
*/
Reactor.prototype.react = function (value) {
this.reactionDepth++;
try {
if (this.reactionDepth > MAX_REACTION_DEPTH) {
throw new Error('Too deeply nested synchronous cyclical reactions disallowed. Use setImmediate.');
Reactor.prototype.reactIfNeeded = function () {
if (!this.active) {
return;
}
this.reaction(value);
}
catch (e) {
// tslint:disable-next-line:no-console - console.error is only called when debugMode is set to true
this.stack && console.error(e.message, this.stack);
throw e;
}
finally {
this.reactionDepth--;
}
};
/**
* Stop reacting on parent changes, will remove this reactor as an observer from the parent which might disconnect the parent.
*/
Reactor.prototype.stop = function () {
if (!this.active) {
return this;
}
this.active = false;
removeObserver(this.parent, this);
return this;
};
/**
* If for some reason any upstream derivable is ordered to disconnect, we have to disconnect as well, which means: stop the reactor.
*/
Reactor.prototype.disconnect = function () {
this.stop();
};
/**
* @internal
* During the mark phase add this reactor to the reactorSink. This way, the transaction knows we exist and we get to `reactIfNeeded`
* later on.
*/
Reactor.prototype.mark = function (reactorSink) {
if (reactorSink.indexOf(this) < 0) {
reactorSink.push(this);
}
};
/**
* Create a new Reactor with lifecycle options. This is the only way to create a new Reactor. Returns a callback function that can
* be used to stop the reactor indefinitely.
*
* @param parent the derivable to react on
* @param reaction the function to call on each reaction
* @param options lifecycle options
* @param ended an optional callback that fires when the reactor is stopped indefinitely (by once or until option)
*/
Reactor.create = function (parent, reaction, options, ended) {
var resolvedOptions = __assign({}, defaultOptions, options);
var from = resolvedOptions.from, until = resolvedOptions.until, when = resolvedOptions.when, once = resolvedOptions.once;
var skipFirst = resolvedOptions.skipFirst;
// Wrap the reaction to enforce skipFirst and once.
var reactor = new Reactor(parent, function (value) {
if (skipFirst) {
skipFirst = false;
// Our controller always has first right to react.
if (this.controller) {
this.controller.reactIfNeeded();
}
else {
reaction(value);
if (once) {
done();
// Check active again, could have been stopped by controller now.
if (!this.active) {
return;
}
var lastValue = this.lastValue;
var nextValue = this.lastValue = this.parent.get();
if (!equals(lastValue, nextValue)) {
this.react(nextValue);
}
};
/**
* React once. Will call the reaction with the current value of parent and remember the current version of the parent to
* be able to determine when to react next.
*/
Reactor.prototype.react = function (value) {
this.reactionDepth++;
try {
if (this.reactionDepth > MAX_REACTION_DEPTH) {
throw new Error('Too deeply nested synchronous cyclical reactions disallowed. Use setImmediate.');
}
this.reaction(value);
}
});
// Listen to when and until conditions, starting and stopping the reactor when
// needed, and stopping the reaction and controller when until becomes true.
var controller = new Reactor(combineWhenUntil(parent, when, until), function (conds) {
if (conds.until) {
done();
catch (e) {
// tslint:disable-next-line:no-console - console.error is only called when debugMode is set to true
this.stack && console.error(e.message, this.stack);
throw e;
}
else if (conds.when) {
reactor.start();
finally {
this.reactionDepth--;
}
else if (reactor.active) {
reactor.stop();
};
/**
* Stop reacting on parent changes, will remove this reactor as an observer from the parent which might disconnect the parent.
*/
Reactor.prototype.stop = function () {
if (!this.active) {
return this;
}
});
// The controller needs to act before the reactor in order to ensure deterministic until and when behavior.
reactor.controller = controller;
// The starter waits until `from` to start the controller.
var starter = new Reactor(toDerivable(from, parent), function (value) {
if (value) {
controller.start();
this.active = false;
removeObserver(this.parent, this);
return this;
};
/**
* If for some reason any upstream derivable is ordered to disconnect, we have to disconnect as well, which means: stop the reactor.
*/
Reactor.prototype.disconnect = function () {
this.stop();
};
/**
* @internal
* During the mark phase add this reactor to the reactorSink. This way, the transaction knows we exist and we get to `reactIfNeeded`
* later on.
*/
Reactor.prototype.mark = function (reactorSink) {
if (reactorSink.indexOf(this) < 0) {
reactorSink.push(this);
}
};
/**
* Create a new Reactor with lifecycle options. This is the only way to create a new Reactor. Returns a callback function that can
* be used to stop the reactor indefinitely.
*
* @param parent the derivable to react on
* @param reaction the function to call on each reaction
* @param options lifecycle options
* @param ended an optional callback that fires when the reactor is stopped indefinitely (by once or until option)
*/
Reactor.create = function (parent, reaction, options, ended) {
var resolvedOptions = __assign({}, defaultOptions, options);
var from = resolvedOptions.from, until = resolvedOptions.until, when = resolvedOptions.when, once = resolvedOptions.once;
var skipFirst = resolvedOptions.skipFirst;
// Wrap the reaction to enforce skipFirst and once.
var reactor = new Reactor(parent, function (value) {
if (skipFirst) {
skipFirst = false;
}
else {
reaction(value);
if (once) {
done();
}
}
});
// Listen to when and until conditions, starting and stopping the reactor when
// needed, and stopping the reaction and controller when until becomes true.
var controller = new Reactor(combineWhenUntil(parent, when, until), function (conds) {
if (conds.until) {
done();
}
else if (conds.when) {
reactor.start();
}
else if (reactor.active) {
reactor.stop();
}
});
// The controller needs to act before the reactor in order to ensure deterministic until and when behavior.
reactor.controller = controller;
// The starter waits until `from` to start the controller.
var starter = new Reactor(toDerivable(from, parent), function (value) {
if (value) {
controller.start();
starter.stop();
}
});
function done() {
starter.stop();
controller.stop();
reactor.stop();
ended && ended();
}
});
function done() {
starter.stop();
controller.stop();
reactor.stop();
ended && ended();
// Go!!!
starter.start();
return done;
};
return Reactor;
}());
function toDerivable(option, derivable) {
if (isDerivable(option)) {
return option;
}
// Go!!!
starter.start();
return done;
};
return Reactor;
}());
function toDerivable(option, derivable) {
if (isDerivable(option)) {
return option;
if (typeof option === 'function') {
return derivation(function () { return unpack(option(derivable)); });
}
return option ? true$ : false$;
}
if (typeof option === 'function') {
return derivation(function () { return unpack(option(derivable)); });
function combineWhenUntil(parent, whenOption, untilOption) {
var when = toDerivable(whenOption, parent);
var until = toDerivable(untilOption, parent);
if (isConstant(when) && isConstant(until)) {
return constant({ when: when.value, until: until.value });
}
return derivation(whenUntil, when, until);
}
return option ? true$ : false$;
}
function combineWhenUntil(parent, whenOption, untilOption) {
var when = toDerivable(whenOption, parent);
var until = toDerivable(untilOption, parent);
if (isConstant(when) && isConstant(until)) {
return constant({ when: when.value, until: until.value });
}
return derivation(whenUntil, when, until);
}
function whenUntil(when, until) { return { when: when, until: until }; }
function whenUntil(when, until) { return { when: when, until: until }; }
exports.atom = atom;
exports.Atom = Atom;
exports.constant = constant;
exports.Constant = Constant;
exports.Derivable = Derivable;
exports.derivation = derivation;
exports.Derivation = Derivation;
exports.lens = lens;
exports.Lens = Lens;
exports.unpack = unpack;
exports.and = and;
exports.firstNotNull = firstNotNull;
exports.isAtom = isAtom;
exports.isConstant = isConstant;
exports.isDerivable = isDerivable;
exports.isDerivation = isDerivation;
exports.isLens = isLens;
exports.lift = lift;
exports.or = or;
exports.scan = scan;
exports.struct = struct;
exports.template = template;
exports.wrapPreviousState = wrapPreviousState;
exports.Reactor = Reactor;
exports.atomic = atomic;
exports.atomically = atomically;
exports.inTransaction = inTransaction;
exports.transact = transact;
exports.transaction = transaction;
exports.clone = clone;
exports.equals = equals;
exports.isPlainObject = isPlainObject;
exports.setDebugMode = setDebugMode;
exports.atom = atom;
exports.Atom = Atom;
exports.constant = constant;
exports.Constant = Constant;
exports.Derivable = Derivable;
exports.derivation = derivation;
exports.Derivation = Derivation;
exports.lens = lens;
exports.Lens = Lens;
exports.unpack = unpack;
exports.and = and;
exports.firstNotNull = firstNotNull;
exports.isAtom = isAtom;
exports.isConstant = isConstant;
exports.isDerivable = isDerivable;
exports.isDerivation = isDerivation;
exports.isLens = isLens;
exports.lift = lift;
exports.or = or;
exports.scan = scan;
exports.struct = struct;
exports.template = template;
exports.wrapPreviousState = wrapPreviousState;
exports.Reactor = Reactor;
exports.atomic = atomic;
exports.atomically = atomically;
exports.inTransaction = inTransaction;
exports.transact = transact;
exports.transaction = transaction;
exports.clone = clone;
exports.equals = equals;
exports.isPlainObject = isPlainObject;
exports.setDebugMode = setDebugMode;
Object.defineProperty(exports, '__esModule', { value: true });
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=sherlock.umd.js.map

Sorry, the diff of this file is not supported yet

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