phadej/menrva

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# menrva

<!-- README.md is autogenerated -->

[![Build Status](https://secure.travis-ci.org/phadej/menrva.svg?branch=master)](http://travis-ci.org/phadej/menrva)
[![NPM version](http://img.shields.io/npm/v/menrva.svg)](https://www.npmjs.org/package/menrva)
[![Dependency Status](https://david-dm.org/phadej/menrva.svg)](https://david-dm.org/phadej/menrva)
[![devDependency Status](https://david-dm.org/phadej/menrva/dev-status.svg)](https://david-dm.org/phadej/menrva#info=devDependencies)
[![Coverage Status](https://img.shields.io/coveralls/phadej/menrva.svg)](https://coveralls.io/r/phadej/menrva?branch=master)
[![Code Climate](http://img.shields.io/codeclimate/github/phadej/menrva.svg)](https://codeclimate.com/github/phadej/menrva)

Ambitious data-flow library.

## Getting Started
Install the module with: `npm install menrva`

```js
var menrva = require('menrva');
menrva.some('awe'); // some, as in awesome?
```

## API


### Signal

The core type of menrva. `Signal` is abstract class, and cannot be created explicitly.

Similar concepts are: *Behaviours* in FRP, *Properties* in bacon.js.

You can add methods to `Signal`'s prototype. They will be available on all signals.


#### signal.map

> map (@ : Signal a, f : a -> b, eq = egal : b -> b -> boolean) : Signal b


#### signal.onValue

> onValue (@ : Signal a, callback : a -> void) -> Unsubscriber

Add value callback. `callback` is immediately executed with the current value of signal.
After than `callback` will be called, each time signal's value changes.

The return value is a function, which will remove the callback if executed.


#### signal.value()

> value (@ : Signal a): Signal a

Returns the current value of signal.


### Source

A signal which value you can set.

Similar concepts are: *Bacon.Model* in bacon.js, *BehaviourSubject* in Rx.


#### source

> source (initialValue : a, eq = egal : a -> a -> boolean) : Source a


#### source.set

> set (@ : Source a, tx : Transaction, value : a) : void


#### source.modify

> modify (@ : Source a, tx : Transaction, f : a -> a) : void

Mofify source value. `f` will be called with current value of signal inside the transaction.


### Signal combinators


#### combine

> combine (Signal a..., f : a... -> b) : Signal b

Applicative n-ary lift. Lift pure function to operate on signals:
```js
var $sum = menrva.combine($a, $b, function (a, b) {
  return a + b;
});
```



### Transaction

One gathers atomic updates into single transaction (to avoid glitches).

```js
var tx = menrva.transaction();
sourceA.set(tx, 42);
sourceB.modify(tx, function (x) { return x + x; });
tx.commit(); // not necessary, transactions are auto-commited
```

There are also optional syntaxes for simple transactions:
```js
menrva.transaction()
  .set(sourceA, 42)
  .modify(sourceB, function (x) { return x + x; })
  .commit();
```
or even
```js
menrva.transaction([sourceA, 42, sourceB, function(x) { return x + x; }]).commit();
```


#### transaction

> transaction (facts) : Transaction

Create transaction.

Shorthand syntax:

> transaction ([sourceA, valueA, sourceB, valueB ...]) : Transaction

If `value` is function, `source.modify(tx, value)` is called; otherwise `source.set(tx, value)`.


#### transaction.commit

Commit the transaction, forcing synchronous data propagation.


#### transaction.rollback

Rollback the transaction. Maybe be called multiple times (consecutives calls are no-op).

*Note: for now `rollback` only resets the pending actions in transactions. Transaction is still valid, and more actions can be added*



### Lens

Lenses are composable functional references.
They allow you to *access* and *modify* data potentially very deep within a structure!


#### source.zoom

> zoom (@ : Source a, path : Path a b, eq = egal : b -> b -> boolean) : Source b

Zoom (or focus) into part specified by `path` of the original signal.
One can `set` and `modify` zoomed signals, they act as sources.

```js
var quux = source.zoom("foo.bar.quux");
```



### Convenience methods

#### signal.log

> signal.log (@ : Signal a, args...) : Unsubscriber

Essentially `signal.onValue(console.log.bind(console, args...))


#### signal.onSpread

> signal.onSpread (@ : Signal [a, b...], callback : a -> b ... -> void) : Unsubscriber

`onValue` with signal's tuple arguments spread.


#### tuple

> tuple (x : Signal a, y : Signal b...) : Signal [a, b...]

Combine signals into tuple.


#### sequence

> sequence [Signal a, Signal b, ..] : Signal [a, b...]

In promise libraries this might be called `all`.


#### record

> record {k: Signal a, l: Signal b...} : Signal {k: a, l: b...}

Like `sequence` but for records i.e. objects.



### Equalities

#### egal

> egal (a, b) : boolean

Identity check. `Object.is`. http://wiki.ecmascript.org/doku.php?id=harmony:egal



### Option

Also known as `Maybe`.


#### option.equals

> equals (@ : option a, other : *, eq = eqal : a -> a -> boolean) : boolean

Equality check.


#### option.map

> map (@ : option a, f : a -> b) : option b


#### option.elim

> elim (@ : option a, x : b, f : a -> b) : b



#### option.orElse

> orElse (@ : option a, x : a) : a



## Contributing


In lieu of a formal styleguide, take care to maintain the existing coding style.

Add tests for any new or changed functionality. 100% coverage isn't hard. Semantic coverage is important too though.

Note: `README.md` is autogenerated file.

## Release History


- **0.0.7** `sequence` and `record`
- **0.0.6** Convenience methods
- **0.0.5** Lens
- **0.0.4** Internal improvements
- **0.0.3** Slight changes in API
- **0.0.2** Basic data-flow functionality
- **0.0.1** Name reservation

## License

Copyright (c) 2014 Oleg Grenrus.
Licensed under the MIT license.