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

pacta

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pacta - npm Package Compare versions

Comparing version 0.0.4 to 0.1.0

.npmignore

149

lib/pacta.js

@@ -6,2 +6,3 @@ var events = require('events');

this.resolved = false;
this.rejected = false;

@@ -14,14 +15,57 @@ if (arguments.length) {

/* Populate a promise with its final value. */
Promise.prototype.resolve = function (x) {
this.value = x;
this.resolved = true;
this.emitter.emit('resolved', x);
Promise.prototype.resolve = Promise.prototype.fulfill = function (x) {
if (this.state() === 'pending') {
this.value = x;
this.resolved = true;
this.emitter.emit('resolved', x);
}
};
/* Reject a promise, populating it with a reason. */
Promise.prototype.reject = function (reason) {
if (this.state() === 'pending') {
this.reason = reason;
this.rejected = true;
this.emitter.emit('rejected', reason);
}
};
/* Return a promise's current state. */
Promise.prototype.state = function () {
if (this.resolved) {
return 'fulfilled';
} else if (this.rejected) {
return 'rejected';
} else {
return 'pending';
}
};
/* onRejected :: Promise a -> (a -> b) -> Promise b */
Promise.prototype.onRejected = function (f) {
var promise = new Promise(),
reason = this.reason;
if (this.rejected) {
process.nextTick(function () {
promise.resolve(f(reason));
});
} else {
this.emitter.once('rejected', function (reason) {
promise.resolve(f(reason));
});
}
return promise;
};
/* map :: Promise a -> (a -> b) -> Promise b */
Promise.prototype.map = function (f) {
var promise = new Promise();
var promise = new Promise(),
value = this.value;
if (this.resolved) {
promise.resolve(f(this.value));
process.nextTick(function () {
promise.resolve(f(value));
});
} else {

@@ -38,21 +82,17 @@ this.emitter.once('resolved', function (x) {

Promise.prototype.chain = function (f) {
if (this.resolved) {
return f(this.value);
} else {
var promise = new Promise();
var promise = new Promise();
/* Map over the given Promise a with (a -> Promise b), returning
* a new Promise (Promise b). Map over that, thereby gaining access to
* the inner Promise b. Map over that in order to get to the inner value
* of b and resolve another promise with it. Return that promise as
* it is equivalent to Promise b.
*/
this.map(f).map(function (x) {
x.map(function (y) {
promise.resolve(y);
});
/* Map over the given Promise a with (a -> Promise b), returning a new
* Promise (Promise b). Map over that, thereby gaining access to the inner
* Promise b. Map over that in order to get to the inner value of b and
* resolve another promise with it. Return that promise as it is equivalent
* to Promise b.
*/
this.map(f).map(function (x) {
x.map(function (y) {
promise.resolve(y);
});
});
return promise;
}
return promise;
};

@@ -85,5 +125,5 @@

/* conjoin :: Promise a -> Promise b -> Promise [a b]
* conjoin :: Promise [a] -> Promise b -> Promise [a b]
* conjoin :: Promise a -> Promise [b] -> Promise [a b]
/* conjoin :: Promise a -> Promise b -> Promise [a b]
* conjoin :: Promise a -> Promise [b] -> Promise [a b]
* conjoin :: Promise [a] -> Promise b -> Promise [a b]
* conjoin :: Promise [a] -> Promise [b] -> Promise [a b]

@@ -119,2 +159,61 @@ */

/* Compatibility with the Promises/A+ specification. */
Promise.prototype.then = function (onFulfilled, onRejected) {
var promise = new Promise(),
isPromise = function (x) {
return x !== null && typeof x === 'object' &&
typeof x.then === 'function';
};
if (typeof onFulfilled === 'function') {
this.map(function (x) {
try {
var value = onFulfilled(x);
if (isPromise(value)) {
value.then(function (x) {
promise.resolve(x);
}, function (reason) {
promise.reject(reason);
});
} else {
promise.resolve(value);
}
} catch (e) {
promise.reject(e);
}
});
} else {
this.map(function (x) {
promise.resolve(x);
});
}
if (typeof onRejected === 'function') {
this.onRejected(function (reason) {
try {
var reason = onRejected(reason);
if (isPromise(reason)) {
reason.then(function (x) {
promise.resolve(x);
}, function (reason) {
promise.reject(reason);
});
} else {
promise.resolve(reason);
}
} catch (e) {
promise.reject(e);
}
});
} else {
this.onRejected(function (reason) {
promise.reject(reason);
});
}
return promise;
};
/* of :: a -> Promise a */

@@ -121,0 +220,0 @@ Promise.of = function (x) {

11

package.json
{
"name": "pacta",
"description": "An algebraic implementation of Promises.",
"description": "An algebraic, Promises/A+ compliant implementation of Promises.",
"homepage": "https://github.com/mudge/pacta",
"author": "Paul Mucur (http://mudge.name)",
"keywords": ["promises", "monad", "functor"],
"version": "0.0.4",
"keywords": ["promises", "monad", "functor", "promises-aplus"],
"version": "0.1.0",
"main": "./lib/pacta.js",
"dependencies": {},
"devDependencies": { "mocha": "1.10.0" },
"devDependencies": {
"mocha": "1.10.0",
"promises-aplus-tests": "1.3.1"
},
"scripts": { "test": "mocha" },

@@ -12,0 +15,0 @@ "repository": {

# pacta [![Build Status](https://travis-ci.org/mudge/pacta.png?branch=master)](https://travis-ci.org/mudge/pacta)
This is an implementation of algebraic Promises in
[node.js](http://nodejs.org).
```javascript
{ 'pacta': '0.1.0' }
```
This is an implementation of [algebraic][Fantasy Land], [Promises/A+][A+]
compliant Promises in [node.js](http://nodejs.org).
Promises can be thought of as objects representing a value that may not have
been calculated yet (similar to the [Maybe monad][Maybe]). An obvious example
is the result of an asynchronous HTTP request: it's not clear *when*
the request will be fulfilled but it will be at some point in the future.
Having actual Promise objects representing these eventual values allows you
to compose, transform and act on them without worrying about their time or
sequence of execution.
been calculated yet (they are sometimes referred to as `Deferred`s).
For a worked example of this, see the
An obvious example is the result of an asynchronous HTTP request: it's not
clear *when* the request will be fulfilled but it will be at some point in the
future. Having actual Promise objects representing these eventual values
allows you to compose, transform and act on them without worrying about their
time or sequence of execution.
At their most basic, an empty promise can be created and resolved like so:
```javascript
var Promise = require('pacta').Promise;
var p = new Promise();
setTimeout(function () {
/* Populate the promise with its final value. */
p.resolve(1);
}, 1000);
```
Promises can also be marked as `rejected` (viz. represent an error state) like
so:
```javascript
/* Mark the promise as rejected with a reason. */
p.reject('The server could not be found.');
```
For a worked example of using promises, see the
[two](https://github.com/mudge/pacta/blob/master/example/codenames.js)
[example programs](https://github.com/mudge/pacta/blob/master/example/codenames-2.js)
[example
programs](https://github.com/mudge/pacta/blob/master/example/codenames-2.js)
and [sample HTTP

@@ -23,3 +50,3 @@ client](https://github.com/mudge/pacta/blob/master/example/promised-http.js)

in the [Fantasy Land
Specification](https://github.com/puffnfresh/fantasy-land):
Specification][Fantasy Land]:

@@ -40,5 +67,17 @@ * [Semigroups](https://github.com/puffnfresh/fantasy-land#semigroup) (through

As well as above, Pacta also provides the following functions for creating and
working with Promises of lists:
Pacta's promises are compliant with the [Promises/A+
specification](http://promises-aplus.github.io/promises-spec), providing
a [`then` method](#promisethenonfulfilled-onrejected).
Promises are resolved (or fulfilled) with
[`Promise#resolve`](#promiseresolvex) and rejected with
[`Promise#rejectreason`](#promiserejectreason).
To execute code on rejection without using
[`Promise#then`](#promisethenonfulfilled-onrejected), use
[`Promise#onRejected`](#promiseonrejectedf).
Pacta also provides the following functions for creating and working with
Promises of lists:
* [`Promise#conjoin`](#promiseconjoinp) to concatenate promises into a list of

@@ -75,5 +114,2 @@ values regardless of their original type meaning that non-Monoid types can

Note that Pacta does not handle errors or the concept of a failed promise as
yet.
See [the test

@@ -83,2 +119,4 @@ suite](https://github.com/mudge/pacta/blob/master/test/pacta_test.js) for more

[A+]: http://promises-aplus.github.io/promises-spec/
[Fantasy Land]: https://github.com/puffnfresh/fantasy-land
[Maybe]: https://en.wikipedia.org/wiki/Monad_(functional_programming)#The_Maybe_monad

@@ -116,6 +154,21 @@

p2.append(p).explode(function (x, y) {
p2.append(p).spread(function (x, y) {
console.log(x); //=> 'bar'
console.log(y); //=> 'Foo'
});
var p4 = new Promise();
setTimeout(function () {
p4.reject('Error!');
}, 1000);
p4.onRejected(function (reason) {
console.error('Failed due to', reason);
}); //=> Failed due to Error!
p4.then(function (value) {
console.log('Success!', value);
}, function (reason) {
console.error('Failure!', reason);
}); //=> Failure! Error!
```

@@ -152,2 +205,13 @@

*This function can also be called as `Promise#fulfill`.*
### `Promise#reject(reason)`
```javascript
var promise = new Promise();
promise.reject('Errored out!');
```
Mark a promise as rejected, populating it with a reason.
### `Promise#map(f)`

@@ -163,2 +227,6 @@

}); //=> Promise.of(4)
promise.map(function (x) {
return Promise.of(x * 2);
}); //=> Promise.of(Promise.of(4))
```

@@ -180,2 +248,41 @@

### `Promise#then([onFulfilled[, onRejected]])`
```javascript
promise.then(function (value) {
return x * 2;
}); //=> Promise.of(4)
promise.then(function (value) {
return Promise.of(x * 2);
}); //=> Promise.of(4)
promise.then(function (value) {
console.log('Success!', value);
}, function (reason) {
console.error('Error!', reason);
});
```
An implementation of the [Promises/A+ `then`
method](http://promises-aplus.github.io/promises-spec/#the__method), taking an
optional `onFulfilled` and `onRejected` function to call when the promise is
fulfilled or rejected respectively.
Like [`Promise#map`](#promisemapf), `then` returns a promise itself and can be
chained.
### `Promise#onRejected(f)`
```javascript
var p = new Promise();
p.reject('Error!');
p.onRejected(function (reason) {
console.error('Failed:', reason);
});
```
Identical to [`Promise#map`](#promisemapf) but only executed when a promise is
rejected rather than resolved.
### `Promise#concat(p)`

@@ -182,0 +289,0 @@

var assert = require('assert'),
Promise = require('../lib/pacta').Promise;
Promise = require('../lib/pacta').Promise,
adapter = require('./pacta_adapter');

@@ -27,5 +28,6 @@ describe('Promise', function () {

describe('.of', function () {
it('wraps a value in a new promise', function () {
it('wraps a value in a new promise', function (done) {
Promise.of(1).map(function (x) {
assert.equal(1, x);
done();
});

@@ -35,2 +37,118 @@ });

describe('#state', function () {
it('is pending for unfulfilled and unrejected promises', function () {
var p = new Promise();
assert.equal('pending', p.state());
});
it('is fulfilled for fulfilled promises', function () {
var p = Promise.of(1);
assert.equal('fulfilled', p.state());
});
it('is rejected for rejected promises', function () {
var p = new Promise();
p.reject('error');
assert.equal('rejected', p.state());
});
});
describe('#resolve', function () {
it('resolves a promise with its final value', function () {
var p = new Promise();
p.resolve(1);
assert.equal('fulfilled', p.state());
});
it('triggers any listeners for resolution', function (done) {
var triggered = false,
p = new Promise();
p.map(function () {
triggered = true;
done();
});
p.resolve(1);
assert.ok(triggered);
});
it('does nothing to rejected promises', function () {
var p = new Promise();
p.reject('error');
p.resolve(1);
assert.equal('rejected', p.state());
});
it('does not trigger listeners if the promise is rejected', function () {
var triggered = false,
p = new Promise();
p.reject('error');
p.map(function () {
triggered = true;
});
p.resolve(1);
assert.ok(!triggered);
});
});
describe('#reject', function () {
it('rejects a promise, setting a reason', function () {
var p = new Promise();
p.reject('error');
assert.equal('rejected', p.state());
});
it('does nothing to fulfilled promises', function () {
var p = Promise.of(1);
p.reject('error');
assert.equal('fulfilled', p.state());
});
it('triggers onRejected listeners', function (done) {
var triggered = false,
p = new Promise();
p.onRejected(function (reason) {
triggered = true;
done();
});
p.reject('error');
assert.ok(triggered);
});
it('does not trigger onRejected listeners if already fulfilled', function () {
var triggered = false,
p = Promise.of(1);
p.onRejected(function (reason) {
triggered = true;
});
p.reject('error');
assert.ok(!triggered);
});
});
describe('#onRejected', function () {
it('binds a listener to be fired on rejection', function (done) {
var p = new Promise();
p.reject('error');
p.onRejected(function (reason) {
assert.equal('error', reason);
done();
});
});
});
describe('#map', function () {

@@ -106,2 +224,66 @@ it('yields the value of the promise', function (done) {

describe('#then', function () {
it('yields its value like #map', function (done) {
p.then(function (x) {
assert.equal('foo', x);
done();
});
});
it('can be chained when returning a value', function (done) {
p.then(function (x) {
return x + '!';
}).then(function (x) {
assert.equal('foo!', x);
done();
});
});
it('does not wrap a promise in a promise', function (done) {
p.then(function (x) {
return Promise.of(x);
}).map(function (x) {
assert.equal('foo', x);
done();
});
});
it('always returns a promise', function () {
assert.equal('object', typeof p.then());
});
it('returns a fulfilled promise with the return value of onRejected', function (done) {
var p = new Promise();
p.reject('foo');
var p2 = p.then(function (value) {
return 1;
}, function (reason) {
return 'error';
});
p2.map(function (x) {
assert.equal('error', x);
assert.equal('fulfilled', p2.state());
done();
});
});
it('assumes the return value of onFulfilled', function (done) {
var p = Promise.of('foo'),
p2 = p.then(function (value) {
return 1;
}, function (reason) {
return 'error';
});
p2.map(function (x) {
assert.equal(1, x);
assert.equal('fulfilled', p2.state());
done();
});
});
});
describe('#concat', function () {

@@ -384,2 +566,6 @@ it('fulfils the associativity property of semigroups #1', function (done) {

});
describe('Promises/A+ compliance', function () {
require('promises-aplus-tests').mocha(adapter);
});
});

@@ -386,0 +572,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