Socket
Socket
Sign inDemoInstall

fluture

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fluture - npm Package Compare versions

Comparing version 1.0.3 to 1.1.0

97

fluture.js

@@ -104,2 +104,3 @@ //// ____ _ _

const fid = f => f.name ? f.name : '<anonymous>';
const ordinal = ['first', 'second', 'third', 'fourth', 'fifth'];

@@ -142,3 +143,3 @@ //Partially apply a function with a single argument.

throw new TypeError(
`${it} expects argument ${at} to ${expected}\n Actual: ${show(actual)}`
`${it} expects its ${ordinal[at]} argument to ${expected}\n Actual: ${show(actual)}`
);

@@ -215,2 +216,6 @@ }

function check$swap(it){
if(!isFuture(it)) error$invalidContext('Future#swap', it);
}
function check$race(it, m){

@@ -232,2 +237,27 @@ if(!isFuture(it)) error$invalidContext('Future#race', it);

function check$hook(it, f, g){
if(!isFuture(it)) error$invalidContext('Future#hook', it);
if(!isFunction(f)) error$invalidArgument('Future#hook', 0, 'be a function', f);
if(!isFunction(g)) error$invalidArgument('Future#hook', 1, 'be a function', g);
}
function check$hook$f(m, f, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the first function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: ${show(x)}`
);
}
function check$hook$g(m, g, x){
if(!isFuture(m)) throw new TypeError(
'Future#hook expects the second function its given to return a Future'
+ `\n Actual: ${show(m)}\n From calling: ${showf(g)}\n With: ${show(x)}`
);
}
function check$finally(it, m){
if(!isFuture(it)) error$invalidContext('Future#finally', it);
if(!isFuture(m)) error$invalidArgument('Future#finally', 0, 'be a Future', m);
}
function check$value(it, f){

@@ -416,2 +446,10 @@ if(!isFuture(it)) error$invalidContext('Future#value', it);

function Future$swap(){
check$swap(this);
const _this = this;
return new FutureClass(function Future$swap$fork(rej, res){
_this._f(res, rej);
});
}
function Future$toString(){

@@ -456,2 +494,38 @@ return `Future(${this._f.toString()})`;

function Future$hook(f, g){
check$hook(this, f, g);
const _this = this;
return new FutureClass(function Future$hook$fork(rej, res){
_this.fork(rej, function Future$hook$res(r){
const m = g(r);
check$hook$g(m, g, r);
m._f(e => {
const c = f(r);
check$hook$f(c, f, r);
c._f(rej, _ => rej(e))
}, x => {
const c = f(r);
check$hook$f(c, f, r);
c._f(rej, _ => res(x))
})
});
});
}
function Future$finally(m){
check$finally(this, m);
const _this = this;
return new FutureClass(function Future$finally$fork(rej, res){
_this._f(function Future$finally$rej(e){
m._f(rej, function Future$finally$rej$res(){
rej(e);
});
}, function Future$finally$res(x){
m._f(rej, function Future$finally$res$res(){
res(x);
});
});
});
}
function Future$value(f){

@@ -519,2 +593,3 @@ check$value(this, f);

ap: Future$ap,
swap: Future$swap,
toString: Future$toString,

@@ -525,2 +600,4 @@ inspect: Future$toString,

fold: Future$fold,
hook: Future$hook,
finally: Future$finally,
value: Future$value,

@@ -586,3 +663,3 @@ promise: Future$promise,

if(m && typeof m[method] === 'function') return m[method](a);
error$invalidArgument(`Future.${method}`, 1, `have a "${method}" method`, m);
error$invalidArgument(`Future.${method}`, 0, `have a "${method}" method`, m);
};

@@ -607,2 +684,15 @@ f.toString = () => `function dispatch$${method}(m, a){ m.${method}(a) }`;

//Creates a dispatcher for a binary method, but takes the object first rather than last.
function createInvertedBinaryDispatcher(method){
const f = function invertedBinaryDispatch(m, a, b){
if(arguments.length === 1) return unaryPartial(f, m);
if(arguments.length === 2) return binaryPartial(f, m, a);
if(m && typeof m[method] === 'function') return m[method](a, b);
error$invalidArgument(`Future.${method}`, 0, `have a "${method}" method`, m);
};
f.toString = () => `function dispatch$${method}(m, a, b){ m.${method}(a, b) }`;
f.inspect = () => `[Function: dispatch$${method}]`;
return f;
}
Future.chain = createUnaryDispatcher('chain');

@@ -614,2 +704,3 @@ Future.chainRej = createUnaryDispatcher('chainRej');

Future.ap = createInvertedUnaryDispatcher('ap');
Future.swap = createNullaryDispatcher('swap');
Future.fork = createBinaryDispatcher('fork');

@@ -619,2 +710,4 @@ Future.race = createUnaryDispatcher('race');

Future.fold = createBinaryDispatcher('fold');
Future.hook = createInvertedBinaryDispatcher('hook');
Future.finally = createUnaryDispatcher('finally');
Future.value = createUnaryDispatcher('value');

@@ -621,0 +714,0 @@ Future.promise = createNullaryDispatcher('promise');

10

package.json
{
"name": "fluture",
"version": "1.0.3",
"version": "1.1.0",
"description": "A mathematically correct alternative to Promises for asynchronous control flow",

@@ -17,4 +17,4 @@ "main": "fluture.js",

"test:opt": "node --allow-natives-syntax --trace-opt --trace-deopt --trace-inlining scripts/test-opt",
"test:unit": "node --harmony-destructuring ./node_modules/.bin/_mocha --ui bdd --reporter spec --check-leaks --full-trace",
"test:coverage": "node --harmony-destructuring node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter dot --bail --check-leaks && codecov"
"test:unit": "node ./node_modules/.bin/_mocha --ui bdd --reporter spec --check-leaks --full-trace",
"test:coverage": "node node_modules/.bin/istanbul cover --report html ./node_modules/.bin/_mocha -- --ui bdd --reporter dot --bail --check-leaks && codecov"
},

@@ -59,3 +59,3 @@ "author": "Aldwin Vlasblom <aldwin.vlasblom@gmail.com> (https://github.com/Avaq)",

"data.task": "^3.0.0",
"eslint": "^2.2.0",
"eslint": "^2.13.1",
"istanbul": "^0.4.2",

@@ -71,4 +71,4 @@ "jsverify": "^0.7.1",

"rimraf": "^2.4.3",
"sanctuary": "^0.10.0"
"sanctuary": "^0.11.1"
}
}

@@ -18,6 +18,19 @@ # Fluture

## Usage
```js
const Future = require('fluture');
const getPackageName = file =>
Future.node(done => fs.readFile(file, 'utf8', done))
.chain(Future.encase(JSON.parse))
.map(x => x.name);
getPackageName('package.json')
.fork(console.error, console.log);
//> "fluture"
```
## Table of contents
- [Table of contents](#table-of-contents)
- [Usage](#usage)
- [Motivation and Features](#motivation-and-features)

@@ -35,14 +48,19 @@ - [Documentation](#documentation)

* [node](#node)
1. [Consuming Futures](#consuming-futures)
* [fork](#fork)
* [value](#value)
* [promise](#promise)
1. [Transforming Futures](#transforming-futures)
* [map](#map)
* [mapRej](#maprej)
* [bimap](#bimap)
* [chain](#chain)
* [ap](#ap)
* [swap](#swap)
1. [Error handling](#error-handling)
* [mapRej](#maprej)
* [chainRej](#chainrej)
* [ap](#ap)
* [fold](#fold)
1. [Resource management](#resource-management)
* [hook](#hook)
* [finally](#finally)
1. [Consuming Futures](#consuming-futures)
* [fork](#fork)
* [value](#value)
* [promise](#promise)
1. [Parallelism](#parallelism)

@@ -55,2 +73,3 @@ * [race](#race)

* [isForkable](#isforkable)
* [cache](#cache)
* [do](#do)

@@ -61,15 +80,2 @@ 1. [Futurization](#futurization)

## Usage
```js
const Future = require('fluture');
const program = file =>
Future.node(done => fs.readFile(file, 'utf8', done))
.chain(Future.encase(JSON.parse))
.map(x => x.name)
.fork(console.error, console.log);
program('package.json');
//> "fluture"
```
## Motivation and Features

@@ -91,5 +97,8 @@

[Hindley-Milner][9] type signatures are used to document functions. A list of
all types used within these signatures follows:
[Hindley-Milner][9] type signatures are used to document functions. Signatures
starting with a `.` refer to "static" functions, whereas signatures starting
with a `#` refer to functions on the prototype.
A list of all types used within the signatures follows:
- **Forkable** - Any Object with a `fork` method that takes at least two

@@ -132,2 +141,3 @@ arguments. This includes instances of Fluture, instances of Task from

#### of
##### `#of :: a -> Future _ a`
##### `.of :: a -> Future _ a`

@@ -221,61 +231,2 @@

### Consuming Futures
#### fork
##### `#fork :: Future a b ~> (a -> Void), (b -> Void) -> Void`
##### `.fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void`
Execute the Future by calling the `fork` function that was passed to it at
[construction](#creation) with the `reject` and `resolve` callbacks. Futures are
*lazy*, which means even if you've `map`ped or `chain`ed over them, they'll do
*nothing* if you don't eventually fork them.
```js
Future.of('world').fork(
err => console.log(`Oh no! ${err.message}`),
thing => console.log(`Hello ${thing}!`)
);
//> "Hello world!"
Future.reject(new Error('It broke!')).fork(
err => console.log(`Oh no! ${err.message}`),
thing => console.log(`Hello ${thing}!`)
);
//> "Oh no! It broke!"
const consoleFork = Future.fork(console.error, console.log);
consoleFork(Future.of('Hello'));
//> "Hello"
```
#### value
##### `#value :: Future a b ~> (b -> Void) -> Void`
##### `.value :: (b -> Void) -> Future a b -> Void`
Extracts the value from a resolved Future by forking it. Only use this function
if you are sure the Future is going to be resolved, for example; after using
`.fold()`. If the Future rejects and `value` was used, an (likely uncatchable)
`Error` will be thrown.
```js
Future.reject(new Error('It broke'))
.fold(S.Left, S.Right)
.value(console.log)
//> Left([Error: It broke])
```
#### promise
##### `#promise :: Future a b ~> Promise b a`
##### `.promise :: Future a b -> Promise b a`
An alternative way to `fork` the Future. This eagerly forks the Future and
returns a Promise of the result. This is useful if some API wants you to give it
a Promise. It's the only method which forks the Future without a forced way to
handle the rejection branch, which means it's considered dangerous to use.
```js
Future.of('Hello').promise().then(console.log);
//> "Hello"
```
### Transforming Futures

@@ -301,17 +252,2 @@

#### mapRej
##### `#mapRej :: Future a b ~> (a -> c) -> Future c b`
##### `.mapRej :: (a -> b) -> Future a c -> Future b c`
Map over the **rejection** reason of the Future. This is like `map`, but for the
rejection branch.
```js
Future.reject(new Error('It broke!')).mapRej(err => {
return new Error('Some extra info: ' + err.message);
})
.fork(console.error, console.log)
//! [Some extra info: It broke!]
```
#### bimap

@@ -353,18 +289,2 @@ ##### `#bimap :: Future a b ~> (a -> c) -> (b -> d) -> Future c d`

#### chainRej
##### `#chainRej :: Future a b ~> (a -> Future a c) -> Future a c`
##### `.chainRej :: (a -> Future a c) -> Future a b -> Future a c`
Chain over the **rejection** reason of the Future. This is like `chain`, but for
the rejection branch.
```js
Future.reject(new Error('It broke!')).chainRej(err => {
console.error(err);
return Future.of('All is good')
})
.fork(console.error, console.log)
//> "All is good"
```
#### ap

@@ -387,2 +307,53 @@ ##### `#ap :: Future a (b -> c) ~> Future a b -> Future a c`

#### swap
##### `#swap :: Future a b ~> Future b a`
##### `.swap :: Future a b -> Future b a`
Resolve with the rejection reason, or reject with the resolution value.
```js
Future.of(new Error('It broke')).swap().fork(console.error, console.log);
//! [It broke]
Future.reject('Nothing broke').swap().fork(console.error, console.log);
//> "Nothing broke"
```
### Error handling
Functions listed under this category allow you to get at or transform the
rejection reason in Futures, or even coerce Futures back into the resolution
branch in several different ways.
#### mapRej
##### `#mapRej :: Future a b ~> (a -> c) -> Future c b`
##### `.mapRej :: (a -> b) -> Future a c -> Future b c`
Map over the **rejection** reason of the Future. This is like `map`, but for the
rejection branch.
```js
Future.reject(new Error('It broke!')).mapRej(err => {
return new Error('Some extra info: ' + err.message);
})
.fork(console.error, console.log)
//! [Some extra info: It broke!]
```
#### chainRej
##### `#chainRej :: Future a b ~> (a -> Future a c) -> Future a c`
##### `.chainRej :: (a -> Future a c) -> Future a b -> Future a c`
Chain over the **rejection** reason of the Future. This is like `chain`, but for
the rejection branch.
```js
Future.reject(new Error('It broke!')).chainRej(err => {
console.error(err);
return Future.of('All is good')
})
.fork(console.error, console.log)
//> "All is good"
```
#### fold

@@ -411,2 +382,119 @@ ##### `#fold :: Future a b ~> (a -> c), (b -> c) -> Future _ c`

### Resource management
Functions listed under this category allow for more fine-grained control over
the flow of acquired values.
#### hook
##### `#hook :: Future a b ~> (b -> Future a c) -> (b -> Future a d) -> Future a d`
##### `.hook :: Future a b -> (b -> Future a c) -> (b -> Future a d) -> Future a d`
Much like [`chain`](#chain), but takes a "cleanup" computation first, which runs
*after* the second settles (successfully or unsuccessfully). This allows for
acquired resources to be disposed, connections to be closed, etc.
```js
const withConnection = Future.hook(
openConnection('localhost'),
closeConnection
);
withConnection(
conn => query(conn, 'EAT * cakes FROM bakery')
)
.fork(console.error, console.log)
```
Take care when using this in combination with [`cache`](#cache). Hooking relies
on the first computation providing a fresh resource every time it's forked.
#### finally
##### `#finally :: Future a b ~> Future a c -> Future a b`
##### `.finally :: Future a c -> Future a b -> Future a b`
Run a second Future after the first settles (successfully or unsuccessfully).
Rejects with the rejection reason from the first or second Future, or resolves
with the resolution value from the first Future.
```js
Future.of('Hello')
.finally(Future.of('All done!').map(console.log))
.fork(console.error, console.log)
//> "All done!"
//> "Hello"
```
Note that the *first* Future is given as the *last* argument to `Future.finally()`:
```js
const program = S.pipe([
Future.of,
Future.finally(Future.of('All done!').map(console.log)),
Future.fork(console.error, console.log)
])
program('Hello')
//> "All done!"
//> "Hello"
```
### Consuming Futures
#### fork
##### `#fork :: Future a b ~> (a -> Void), (b -> Void) -> Void`
##### `.fork :: (a -> Void) -> (b -> Void) -> Future a b -> Void`
Execute the Future by calling the `fork` function that was passed to it at
[construction](#creation) with the `reject` and `resolve` callbacks. Futures are
*lazy*, which means even if you've `map`ped or `chain`ed over them, they'll do
*nothing* if you don't eventually fork them.
```js
Future.of('world').fork(
err => console.log(`Oh no! ${err.message}`),
thing => console.log(`Hello ${thing}!`)
);
//> "Hello world!"
Future.reject(new Error('It broke!')).fork(
err => console.log(`Oh no! ${err.message}`),
thing => console.log(`Hello ${thing}!`)
);
//> "Oh no! It broke!"
const consoleFork = Future.fork(console.error, console.log);
consoleFork(Future.of('Hello'));
//> "Hello"
```
#### value
##### `#value :: Future a b ~> (b -> Void) -> Void`
##### `.value :: (b -> Void) -> Future a b -> Void`
Extracts the value from a resolved Future by forking it. Only use this function
if you are sure the Future is going to be resolved, for example; after using
`.fold()`. If the Future rejects and `value` was used, an (likely uncatchable)
`Error` will be thrown.
```js
Future.reject(new Error('It broke'))
.fold(S.Left, S.Right)
.value(console.log)
//> Left([Error: It broke])
```
#### promise
##### `#promise :: Future a b ~> Promise b a`
##### `.promise :: Future a b -> Promise b a`
An alternative way to `fork` the Future. This eagerly forks the Future and
returns a Promise of the result. This is useful if some API wants you to give it
a Promise. It's the only method which forks the Future without a forced way to
handle the rejection branch, which means it's considered dangerous to use.
```js
Future.of('Hello').promise().then(console.log);
//> "Hello"
```
### Parallelism

@@ -541,2 +629,3 @@

#### cache
##### `.cache :: Future a b -> Future a b`

@@ -591,2 +680,20 @@

Error handling is slightly different in do-notation, you need to [`fold`](#fold)
the error into your control domain, I recommend folding into an [`Either`][7]:
```js
const attempt = Future.fold(S.Left, S.Right);
const ajaxGet = url => Future.reject('Failed to load ' + url);
Future.do(function*(){
const e = yield attempt(ajaxGet('/message'));
return S.either(
e => `Oh no! ${e}`,
x => `Yippee! ${x}`,
e
);
})
.fork(console.error, console.log);
//> "Oh no! Failed to load /message"
```
### Futurization

@@ -593,0 +700,0 @@

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