npm package: @lindem/overseer
Description: code which aids with untyped javascript
Author: Timo Lindemann
Latest version: 0.0.2

# Overseer

Control flow structures and runtime check helpers for untyped JavaScript.

## Predicates

* Predicates are functions that return boolean.
* A special form used throughout this code is the `unaryPredicate`, which is a predicate
  that accepts only one value to check some assumption about that value.
* A `predicateGenerator` is a function that creates `unaryPredicate` functions from some input.
* multiple `unaryPredicates` can be combined with `and` and `or`, or negated with `not`
* the `lodash` library is used throughout this library. It comes with multiple predicates already.

Example of how to combine predicates:

```javascript
import {isInteger} from 'lodash';
import {makeGreaterThanPredicate} from '@lindem/overseer/generators/comparisons';

const isPositiveInteger = and(isInteger, makeGreaterThanPredicate(0));
```

### Invocation Contracts

* A higher-order-function which decorates another function to include invocation checks is called an `invocationContractWrapper`. This includes checks for each of the declared parameters, checks for arity (the number of parameters the function consumes), and checks for
  the return value.
* Checks for parameters, arity and return values are optional.
* Contracts will raise Errors (`throw`) if the contract is breached.

Example of an `invocationContract`:

```javascript
import {isInteger} from 'lodash';
import {InvocationContractBuilder} from '@lindem/overseer/constructs/invocation-contract';
import {
  makeGreaterThanPredicate,
  makeStrictEqualityPredicate
} from '@lindem/overseer/generators/comparisons';

const isNonNegativeInteger = and(isInteger, makeGreaterThanOrEqualPredicate(0));
const isPositiveInteger = and(isInteger, makeGreaterThanPredicate(0));

const decorateUnaryIntegerToIntegerFunction = new InvocationContractBuilder()
  .setParameterPredicates([isNonNegativeInteger])
  .setParameterLength(1)
  .setReturnValuePredicate(isPositiveInteger)
  .build();

// ... elsewhere

function faculty(n) {
  return n <= 1 ? 1 : n * n - 1;
}

const checkedFaculty = decorateUnaryIntegerToIntegerFunction(faculty);

// ... elsewhere

checkedFaculty(3); // yields 6.
checkedFaculty('hi'); // error, "Contract Breached: Malformed Parameter"
checkedFaculty(2, 3); // error, "Contract Breached: This function requires 1 parameter..."
checkedFaculty(); // same as above
```

The advantage of doing it that way is that the code in the actual function can
rely on all checking already being done. Depending on whether the contract is
specified to that extent, all of the following can be reasonably
assumed:

* Assurances made to the decorated function:
  * Parameters passed specification tests.
  * No parameters are missing.
* Assurances made to the caller:
  * The function return value passed its specification.

There is no checking in the actual code, because we just decorated a function
with the contract and are done.

Of course, you do not save keystrokes. The contract can be created elsewhere and
be applied to many functions, though.

If there are both arity checks and parameter predicates while trailing
`undefined`s occur (which may either be missing parameters or parameters
actually having the value `undefined`), parameter predicates will run first.

## Considerations for using these constructs

* This library will not make your application run faster. The constructs herein
  may introduce overhead because of all the extra checking that is going on.