diff --git a/API.md b/API.md index 216fbf6..466bff3 100644 --- a/API.md +++ b/API.md @@ -4,6 +4,12 @@ | -------- | --------- | | [`all`](#all) | `[Promise a] -> Promise [a]` | | [`backoff`](#backoff) | `Number -> Number -> (a... -> Promise b) -> a... -> Promise b` | +| [`combine`](#combine) | `({ k: v } -> { k: v }) -> { k: v }` | +| [`combineAll`](#combineall) | `[a... -> { k: v }] -> { k: v } -> { k: v }` | +| [`combineAllP`](#combineallp) | `[a... -> Promise { k: v }] -> { k: v } -> Promise { k: v }` | +| [`combineP`](#combinep) | `({ k: v } -> Promise { k: v }) -> Promise { k: v }` | +| [`combineWith`](#combinewith) | `(c -> b -> d) (a -> b) -> c -> d` | +| [`combineWithP`](#combinewithp) | `(c -> b -> d) (a -> Promise b) -> Promise c -> Promise d` | | [`convergeP`](#convergep) | `(b -> c -> Promise d) -> [(a -> Promise b), (a -> Promise c)] -> a -> Promise d` | | [`copyProp`](#copyprop) | `String -> String -> { k: v } -> { k: v }` | | [`evolveP`](#evolvep) | `{ k: (v -> Promise v) } -> { k: v } -> Promise { k: v }` | @@ -47,6 +53,74 @@ const fetchImage = opts => { /* async, and might fail sometimes */ } backoff(250, 5, fetchImage) //=> a new function that tries at most 5 times before rejecting ``` +### combine + +```haskell +combine : ({ k: v } -> { k: v }) -> { k: v } +``` + +Accepts a function & an object. Merges the results of the function into the object. + +```js +combine(always({ foo: 1 }), { foo: 2, bar: 3 }) //=> { foo: 1, baz: 3 } +``` + +### combineAll + +```haskell +combineAll : combineAll : [a... -> { k: v }] -> { k: v } -> { k: v } +``` + +Accepts a list of functions & an object. Merges the results of all the functions into the object left-to-right + +```js +combineAll([ always({ foo: 1, bar: 2 }), always({ bar: 3 }) ], { foo: 4, baz: 5 }) //=> { foo: 1, bar: 3, baz: 5 } +``` + +### combineP + +```haskell +combineP : ({ k: v } -> Promise { k: v }) -> Promise { k: v } +``` + +Async version of [`combine`](#combine) + +Accepts an async function & an object. Merges the results of the function into the object. + +```js +combineP(always(resolve({ foo: 1 })), { foo: 2, bar: 3 }) //=> Promise { foo: 1, baz: 3 } +``` + +### combineWith + +```haskell +combineWith : (c -> b -> d) (a -> b) -> c -> d +``` + +Accepts a merging function, a transformation function, and an value. Uses the merging function to merge the results of the transformation function into the value. + +```js +combineWith(multiply, add(2), 3) //=> 15 +combineWith(mergeDeepLeft, always({ foo: { bar: 1, bip: 2 } }), { foo: { bar: 3, baz: 4 } }) + //=> { foo: { bar: 3, baz: 4, bip: 2 } } +``` + +### combineWithP + +```haskell +combineWithP : (c -> b -> d) (a -> Promise b) -> Promise c -> Promise d +``` + +Async version of [`combineWith`](#combinewith). + +Accepts a merging function, an async transformation function, and an value. Uses the merging function to merge the results of the transformation function into the value. + +```js +combineWith(multiply, compose(resolve, add(2)), 3) //=> Promise 15 +combineWith(mergeDeepLeft, always(resolve({ foo: { bar: 1, bip: 2 } })), { foo: { bar: 3, baz: 4 } }) + //=> Promise { foo: { bar: 3, baz: 4, bip: 2 } } +``` + ### convergeP ```haskell diff --git a/index.js b/index.js index 1c51612..d28bba9 100644 --- a/index.js +++ b/index.js @@ -1,16 +1,22 @@ -exports.all = require('./lib/all') -exports.backoff = require('./lib/backoff') -exports.convergeP = require('./lib/convergeP') -exports.copyProp = require('./lib/copyProp') -exports.evolveP = require('./lib/evolveP') -exports.juxtP = require('./lib/juxtP') -exports.mapP = require('./lib/mapP') -exports.move = require('./lib/move') -exports.normalizeBy = require('./lib/normalizeBy') -exports.overP = require('./lib/overP') -exports.promisify = require('./lib/promisify') -exports.reject = require('./lib/reject') -exports.rename = require('./lib/rename') -exports.resolve = require('./lib/resolve') -exports.tapP = require('./lib/tapP') -exports.validate = require('./lib/validate') +exports.all = require('./lib/all') +exports.backoff = require('./lib/backoff') +exports.combine = require('./lib/combine') +exports.combineAll = require('./lib/combineAll') +exports.combineAllP = require('./lib/combineAllP') +exports.combineP = require('./lib/combineP') +exports.combineWith = require('./lib/combineWith') +exports.combineWithP = require('./lib/combineWithP') +exports.convergeP = require('./lib/convergeP') +exports.copyProp = require('./lib/copyProp') +exports.evolveP = require('./lib/evolveP') +exports.juxtP = require('./lib/juxtP') +exports.mapP = require('./lib/mapP') +exports.move = require('./lib/move') +exports.normalizeBy = require('./lib/normalizeBy') +exports.overP = require('./lib/overP') +exports.promisify = require('./lib/promisify') +exports.reject = require('./lib/reject') +exports.rename = require('./lib/rename') +exports.resolve = require('./lib/resolve') +exports.tapP = require('./lib/tapP') +exports.validate = require('./lib/validate') diff --git a/src/combine.js b/src/combine.js new file mode 100644 index 0000000..baf0fbd --- /dev/null +++ b/src/combine.js @@ -0,0 +1,5 @@ +const merge = require('ramda/src/merge') +const combineWith = require('./combineWith') + +// combine : ({ k: v } -> { k: v }) -> { k: v } +module.exports = combineWith(merge) diff --git a/src/combineAll.js b/src/combineAll.js new file mode 100644 index 0000000..8d3e21c --- /dev/null +++ b/src/combineAll.js @@ -0,0 +1,8 @@ +const compose = require('ramda/src/compose') +const identity = require('ramda/src/identity') +const juxt = require('ramda/src/juxt') +const mergeAll = require('ramda/src/mergeAll') + +// combineAll : [a... -> { k: v }] -> { k: v } -> { k: v } +module.exports = fns => + compose(mergeAll, juxt([ identity, ...fns ])) diff --git a/src/combineAllP.js b/src/combineAllP.js new file mode 100644 index 0000000..20c8f98 --- /dev/null +++ b/src/combineAllP.js @@ -0,0 +1,9 @@ +const composeP = require('ramda/src/composeP') +const identity = require('ramda/src/identity') +const mergeAll = require('ramda/src/mergeAll') + +const juxtP = require('./juxtP') + +// combineAllP : [a... -> Promise { k: v }] -> { k: v } -> Promise { k: v } +module.exports = fns => + composeP(mergeAll, juxtP([ identity, ...fns ])) diff --git a/src/combineP.js b/src/combineP.js new file mode 100644 index 0000000..f3c360d --- /dev/null +++ b/src/combineP.js @@ -0,0 +1,5 @@ +const merge = require('ramda/src/merge') +const combineWithP = require('./combineWithP') + +// combineP : ({ k: v } -> Promise { k: v }) -> Promise { k: v } +module.exports = combineWithP(merge) diff --git a/src/combineWith.js b/src/combineWith.js new file mode 100644 index 0000000..ffc50c1 --- /dev/null +++ b/src/combineWith.js @@ -0,0 +1,9 @@ +const converge = require('ramda/src/converge') +const curry = require('ramda/src/curry') +const identity = require('ramda/src/identity') + +// combineWith : (c -> b -> d) (a -> b) -> c -> d +const combineWith = (mf, f) => + converge(mf, [ identity, f ]) + +module.exports = curry(combineWith) diff --git a/src/combineWithP.js b/src/combineWithP.js new file mode 100644 index 0000000..ccb67e4 --- /dev/null +++ b/src/combineWithP.js @@ -0,0 +1,10 @@ +const curry = require('ramda/src/curry') +const identity = require('ramda/src/identity') + +const convergeP = require('./convergeP') + +// combineWithP : (c -> b -> d) (a -> Promise b) -> Promise c -> Promise d +const combineWithP = (mf, f) => + convergeP(mf, [ identity, f ]) + +module.exports = curry(combineWithP) diff --git a/test/combine.js b/test/combine.js new file mode 100644 index 0000000..a1364f6 --- /dev/null +++ b/test/combine.js @@ -0,0 +1,22 @@ +const { expect } = require('chai') +const property = require('prop-factory') +const always = require('ramda/src/always') + +const { combine } = require('..') + +const whatevs = combine(always({ foo: 'bar' })) + +describe('combine', () => { + const res = property() + + beforeEach(() => + res(whatevs({ baz: 'bip' })) + ) + + it('merges with the results of the function', () => + expect(res()).to.eql({ + foo: 'bar', + baz: 'bip', + }) + ) +}) diff --git a/test/combineAll.js b/test/combineAll.js new file mode 100644 index 0000000..91914cf --- /dev/null +++ b/test/combineAll.js @@ -0,0 +1,26 @@ +const { expect } = require('chai') +const property = require('prop-factory') +const always = require('ramda/src/always') + +const { combineAll } = require('..') + +const whatevs = combineAll([ + always({ foo: 1 }), + always({ bar: 2 }), +]) + +describe('combineAll', () => { + const res = property() + + beforeEach(() => + res(whatevs({ baz: 3 })) + ) + + it('combines the results of all functions', () => + expect(res()).to.eql({ + foo: 1, + bar: 2, + baz: 3, + }) + ) +}) diff --git a/test/combineAllP.js b/test/combineAllP.js new file mode 100644 index 0000000..392b620 --- /dev/null +++ b/test/combineAllP.js @@ -0,0 +1,26 @@ +const { expect } = require('chai') +const property = require('prop-factory') +const always = require('ramda/src/always') + +const { combineAllP } = require('..') + +const whatevs = combineAllP([ + always(Promise.resolve({ foo: 1 })), + always(Promise.resolve({ bar: 2 })), +]) + +describe('combineAll', () => { + const res = property() + + beforeEach(() => + whatevs({ baz: 3 }).then(res) + ) + + it('combines the results of all functions', () => + expect(res()).to.eql({ + foo: 1, + bar: 2, + baz: 3, + }) + ) +}) diff --git a/test/combineP.js b/test/combineP.js new file mode 100644 index 0000000..e3da1c7 --- /dev/null +++ b/test/combineP.js @@ -0,0 +1,22 @@ +const { expect } = require('chai') +const property = require('prop-factory') +const always = require('ramda/src/always') + +const { combineP } = require('..') + +const whatevs = combineP(always(Promise.resolve({ foo: 'bar' }))) + +describe('combine', () => { + const res = property() + + beforeEach(() => + whatevs({ baz: 'bip' }).then(res) + ) + + it('merges with the results of the function', () => + expect(res()).to.eql({ + foo: 'bar', + baz: 'bip', + }) + ) +}) diff --git a/test/combineWith.js b/test/combineWith.js new file mode 100644 index 0000000..4e768f4 --- /dev/null +++ b/test/combineWith.js @@ -0,0 +1,20 @@ +const { expect } = require('chai') +const property = require('prop-factory') +const add = require('ramda/src/add') +const multiply = require('ramda/src/multiply') + +const { combineWith } = require('..') + +const whatevs = combineWith(multiply, add(2)) + +describe('combineWith', () => { + const res = property() + + beforeEach(() => + res(whatevs(3)) + ) + + it('combines with the results of the function', () => + expect(res()).to.equal(15) + ) +}) \ No newline at end of file diff --git a/test/combineWithP.js b/test/combineWithP.js new file mode 100644 index 0000000..3bf2921 --- /dev/null +++ b/test/combineWithP.js @@ -0,0 +1,19 @@ +const { expect } = require('chai') +const property = require('prop-factory') + +const { add, mult } = require('./lib/async') +const { combineWithP } = require('..') + +const whatevs = combineWithP(mult, add(2)) + +describe('combineWith', () => { + const res = property() + + beforeEach(() => + whatevs(3).then(res) + ) + + it('combines with the results of the function', () => + expect(res()).to.equal(15) + ) +}) \ No newline at end of file