Comparing version 1.0.3 to 2.0.0
283
index.js
@@ -0,107 +1,61 @@ | ||
import ResultType from 'result-type' | ||
import ResultCore from 'result-core' | ||
var ResultType = require('result-type') | ||
var ResultCore = require('result-core') | ||
var listen = ResultCore.prototype.listen | ||
export default class Result extends ResultCore { | ||
/** | ||
* Create a Result for a transformation of the value | ||
* of `this` Result | ||
* | ||
* @param {Function} onValue | ||
* @param {Function} onError | ||
* @return {Result} | ||
*/ | ||
/** | ||
* expose `Result` | ||
*/ | ||
then(onValue, onError) { | ||
switch (this.state) { | ||
case 'fail': onValue = onError // falls through | ||
case 'done': | ||
if (!onValue) return this | ||
try { | ||
return coerce(onValue.call(this, this.value)) | ||
} catch (e) { | ||
return failed(e) | ||
} | ||
default: | ||
var x = pending() | ||
this.listen( | ||
handle(x, onValue, 'write', this), | ||
handle(x, onError, 'error', this)) | ||
return x | ||
} | ||
} | ||
module.exports = exports = Result | ||
/** | ||
* Create a child Result destined to fulfill with `value` | ||
* return result.then(function(value){ | ||
* // some side effect | ||
* }).yield(e) | ||
* | ||
* @param {x} value | ||
* @return {Result} | ||
*/ | ||
/** | ||
* expose helpers | ||
*/ | ||
yield(value) { | ||
return this.then(() => value) | ||
} | ||
exports.wrap = exports.done = wrap | ||
exports.transfer = transfer | ||
exports.Type = ResultType | ||
exports.coerce = coerce | ||
exports.failed = failed | ||
exports.unbox = unbox | ||
exports.when = when | ||
exports.read = read | ||
/** | ||
* return a Result for `this[attr]` | ||
* | ||
* @param {String} attr | ||
* @return {Result} | ||
*/ | ||
/** | ||
* the Result class | ||
*/ | ||
function Result(){} | ||
/** | ||
* inherit from ResultCore | ||
*/ | ||
Result.prototype = new ResultCore | ||
Result.prototype.constructor = Result | ||
/** | ||
* Create a Result for a transformation of the value | ||
* of `this` Result | ||
* | ||
* @param {Function} onValue | ||
* @param {Function} onError | ||
* @return {Result} | ||
*/ | ||
Result.prototype.then = function(onValue, onError) { | ||
switch (this.state) { | ||
case 'fail': onValue = onError // falls through | ||
case 'done': | ||
if (!onValue) return this | ||
try { | ||
return coerce(onValue.call(this, this.value)) | ||
} catch (e) { | ||
return failed(e) | ||
} | ||
default: | ||
var x = new Result | ||
this.listen( | ||
handle(x, onValue, 'write', this), | ||
handle(x, onError, 'error', this)) | ||
return x | ||
get(attr) { | ||
return this.then(obj => obj[attr]) | ||
} | ||
} | ||
/** | ||
* read using a node style function | ||
* | ||
* result.node(function(err, value){}) | ||
* | ||
* @param {Function} [callback(error, value)] | ||
* @return {this} | ||
*/ | ||
Result.prototype.node = function(fn){ | ||
if (typeof fn != 'function') return this | ||
return this.read(function(v){ fn(null, v) }, fn) | ||
} | ||
/** | ||
* Create a child Result destined to fulfill with `value` | ||
* | ||
* return result.then(function(value){ | ||
* // some side effect | ||
* }).yield(e) | ||
* | ||
* @param {x} value | ||
* @return {Result} | ||
*/ | ||
Result.prototype.yield = function(value){ | ||
return this.then(function(){ return value }) | ||
} | ||
/** | ||
* return a Result for `this[attr]` | ||
* | ||
* @param {String} attr | ||
* @return {Result} | ||
*/ | ||
Result.prototype.get = function(attr){ | ||
return this.then(function(obj){ return obj[attr] }) | ||
} | ||
/** | ||
* wrap `reason` in a "failed" result | ||
@@ -114,8 +68,3 @@ * | ||
function failed(reason){ | ||
var res = new Result | ||
res.value = reason | ||
res.state = 'fail' | ||
return res | ||
} | ||
export const failed = reason => new Result('fail', reason) | ||
@@ -130,10 +79,11 @@ /** | ||
function wrap(value){ | ||
var res = new Result | ||
res.value = value | ||
res.state = 'done' | ||
return res | ||
} | ||
export const wrap = value => new Result('done', value) | ||
/** | ||
* A pending Result | ||
*/ | ||
export const pending = () => new Result('pending') | ||
/** | ||
* coerce `value` to a Result | ||
@@ -146,14 +96,13 @@ * | ||
function coerce(value){ | ||
export const coerce = value => { | ||
if (!(value instanceof ResultType)) return wrap(value) | ||
if (value instanceof Result) return value | ||
var result = new Result | ||
switch (value.state) { | ||
case 'done': result.write(value.value); break | ||
case 'fail': result.error(value.value); break | ||
default: | ||
(value.listen || listen).call(value, | ||
function(value){ result.write(value) }, | ||
function(error){ result.error(error) }) | ||
case 'done': return wrap(value.value) | ||
case 'fail': return failed(value.value) | ||
} | ||
var result = pending() | ||
value.listen( | ||
value => result.write(value), | ||
error => result.error(error)) | ||
return result | ||
@@ -171,3 +120,2 @@ } | ||
* @param {String} method | ||
* @param {Any} [ctx] | ||
* @return {Function} | ||
@@ -177,10 +125,9 @@ * @api private | ||
function handle(result, fn, method, ctx){ | ||
return typeof fn != 'function' | ||
? function(x){ return result[method](x) } | ||
: function(x){ | ||
const handle = (result, fn, method, ctx) => | ||
typeof fn != 'function' | ||
? x => result[method](x) | ||
: x => { | ||
try { transfer(fn.call(ctx, x), result) } | ||
catch (e) { result.error(e) } | ||
} | ||
} | ||
@@ -200,3 +147,3 @@ /** | ||
function when(value, onValue, onError){ | ||
export const when = (value, onValue, onError) => { | ||
if (value instanceof ResultType) switch (value.state) { | ||
@@ -212,7 +159,5 @@ case 'fail': | ||
default: | ||
var x = new Result | ||
var fn = value.listen || listen // backwards compat | ||
fn.call(value, | ||
handle(x, onValue, 'write', this), | ||
handle(x, onError, 'error', this)) | ||
var x = pending() | ||
value.listen(handle(x, onValue, 'write'), | ||
handle(x, onError, 'error')) | ||
// unbox if possible | ||
@@ -222,4 +167,4 @@ return x.state == 'done' ? x.value : x | ||
if (!onValue) return value | ||
try { return onValue.call(this, value) } | ||
catch (e) { return failed.call(this, e) } | ||
try { return onValue(value) } | ||
catch (e) { return failed(e) } | ||
} | ||
@@ -235,3 +180,3 @@ | ||
function read(value, onValue, onError){ | ||
export const read = (value, onValue, onError) => { | ||
if (value instanceof ResultType) value.read(onValue, onError) | ||
@@ -248,3 +193,3 @@ else onValue(value) | ||
function transfer(a, b){ | ||
export const transfer = (a, b) => { | ||
if (a instanceof ResultType) switch (a.state) { | ||
@@ -254,6 +199,3 @@ case 'done': b.write(a.value); break | ||
default: | ||
var fn = a.listen || listen // backwards compat | ||
fn.call(a, | ||
function(value){ b.write(value) }, | ||
function(error){ b.error(error) }) | ||
a.listen(value => b.write(value), error => b.error(error)) | ||
} else { | ||
@@ -273,3 +215,3 @@ b.write(a) | ||
function unbox(value){ | ||
export const unbox = value => { | ||
if (!(value instanceof ResultType)) return value | ||
@@ -280,1 +222,70 @@ if (value.state == 'done') return value.value | ||
} | ||
/** | ||
* Deferred class | ||
*/ | ||
export class Deferred extends Result { | ||
constructor(fn){ | ||
super('pending') | ||
this.onNeed = fn | ||
this.needed = false | ||
} | ||
/** | ||
* add a trigger aspect to listen. This aspect ensures | ||
* `onNeed` is called the first time someone reads from | ||
* the Deferred result | ||
* | ||
* @param {Function} method | ||
* @return {Function} | ||
* @api private | ||
*/ | ||
listen(onValue, onError) { | ||
super.listen(onValue, onError) | ||
if (this.needed === false) { | ||
this.needed = true | ||
try { | ||
transfer(this.onNeed(), this) | ||
} catch (e) { | ||
this.error(e) | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* create a Deferred which is associated with the | ||
* Function `onNeed`. `onNeed` will only be called | ||
* once someone actually reads from the Deferred. | ||
* | ||
* defer(() => 'hello') | ||
* defer((cb) => cb(null, 'hello')) | ||
* defer((write, error) => write('hello')) | ||
* | ||
* @param {Function} onNeed(write, error) | ||
* @return {Deferred} | ||
*/ | ||
export const defer = onNeed => { | ||
switch (onNeed.length) { | ||
case 2: | ||
return new Deferred(function(){ | ||
const res = pending() | ||
onNeed.call(this, v => res.write(v), e => res.error(e)) | ||
return res | ||
}) | ||
case 1: | ||
return new Deferred(function(){ | ||
const result = pending() | ||
onNeed.call(this, (error, value) => { | ||
if (error != null) result.error(error) | ||
else result.write(value) | ||
}) | ||
return result | ||
}) | ||
default: | ||
return new Deferred(onNeed) | ||
} | ||
} |
{ | ||
"name": "result", | ||
"version": "1.0.3", | ||
"version": "2.0.0", | ||
"description": "reify your results", | ||
"dependencies": { | ||
"result-type": "1.0.0", | ||
"result-core": "1.2.1" | ||
"result-type": "1", | ||
"result-core": "2" | ||
}, | ||
@@ -12,2 +12,3 @@ "devDependencies": { | ||
"serve": "jkroso/serve", | ||
"future-node": "0", | ||
"chai-spies": "*", | ||
@@ -22,2 +23,3 @@ "hydro-chai": "*", | ||
}, | ||
"transpile": [["*.js", "!sourcegraph/babel->js", {"stage": 0}]], | ||
"repository": "git://github.com/jkroso/result.git", | ||
@@ -27,3 +29,3 @@ "keywords": ["result", "promise", "future"], | ||
"license": "MIT", | ||
"files": ["index.js", "defer.js"] | ||
"files": ["index.js"] | ||
} |
@@ -10,13 +10,8 @@ | ||
With your favourite package manager: | ||
`npm install result` | ||
- [packin](//github.com/jkroso/packin): `packin add result` | ||
- [component](//github.com/component/component#installing-packages): `component install jkroso/result` | ||
- [npm](//npmjs.org/doc/cli/npm-install.html): `npm install result` | ||
then in your app: | ||
```js | ||
var Result = require('result') | ||
var defer = require('result/defer') | ||
import Result from 'result' | ||
``` | ||
@@ -23,0 +18,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12164
11
3
247
105
+ Addedresult-core@2.0.1(transitive)
- Removedresult-core@1.2.1(transitive)
Updatedresult-core@2
Updatedresult-type@1