rubico
Version:
[a]synchronous functional programming
100 lines (96 loc) • 3.2 kB
JavaScript
const isPromise = require('./_internal/isPromise')
const objectAssign = require('./_internal/objectAssign')
const __ = require('./_internal/placeholder')
const curry2 = require('./_internal/curry2')
const curry3 = require('./_internal/curry3')
const functionObjectAll = require('./_internal/functionObjectAll')
// _assign(object Object, funcs Object<function>) -> Promise|Object
const _assign = function (object, funcs) {
const result = functionObjectAll(funcs, [object])
return isPromise(result)
? result.then(curry3(objectAssign, {}, object, __))
: ({ ...object, ...result })
}
/**
* @name assign
*
* @synopsis
* ```coffeescript [specscript]
* args Array<any>
*
* type UnarySyncOrAsyncResolver = any=>Promise|any
*
* objectResolversOrPromisesOrValues Object<UnarySyncOrAsyncResolver|Promise|any>
*
* assign(argumentObject Promise|Object, objectResolversOrPromisesOrValues) -> resultObject
* assign(objectResolversOrPromisesOrValues)(argumentObject Object) -> resultObject
* ```
*
* @description
* Function equivalent to [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). Constructs an object `result` from an object `objectResolversOrPromisesOrValues` of resolvers, promises, values, or a mix thereof and an argument object `argumentObject`.
*
* If any values of `objectResolversOrPromisesOrValues` are resolvers, `assign` provides the `argumentObject` to those resolvers to resolve the values for assignment in `resultObject`.
*
* ```javascript [playground]
* const assignSquaredAndCubed = assign({
* squared: ({ number }) => number ** 2,
* cubed: ({ number }) => number ** 3,
* n: 1,
* })
*
* console.log(assignSquaredAndCubed({ number: 2 }))
* // { number: 2, squared: 4, cubed: 8, n: 1 }
*
* console.log(assignSquaredAndCubed({ number: 3 }))
* // { number: 3, squared: 9, cubed: 27, n: 1 }
* ```
*
* If any of the resolvers in `objectResolversOrPromisesOrValues` are asynchronous, `assign` returns a promise of `resultObject`.
*
* ```javascript [playground]
* const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
*
* const asyncAssignTotal = assign({
* async total({ numbers }) {
* await sleep(500)
* return numbers.reduce((a, b) => a + b)
* },
* })
*
* asyncAssignTotal({ numbers: [1, 2, 3, 4, 5] }).then(console.log)
* // { numbers: [1, 2, 3, 4, 5], total: 15 }
* ```
*
* Any promises passed in argument position are resolved for their values before further execution. This only applies to the eager version of the API.
*
* ```javascript [playground]
* assign(Promise.resolve({}), {
* a() {
* return 1
* },
* b() {
* return 2
* },
* }).then(console.log)
* ```
*
* See also:
* * [pipe](/docs/pipe)
* * [all](/docs/all)
* * [get](/docs/get)
* * [set](/docs/set)
* * [pick](/docs/pick)
* * [omit](/docs/omit)
* * [forEach](/docs/forEach)
*
* @execution concurrent
*/
const assign = function (arg0, arg1) {
if (arg1 == null) {
return curry2(_assign, __, arg0)
}
return isPromise(arg0)
? arg0.then(curry2(_assign, __, arg1))
: _assign(arg0, arg1)
}
module.exports = assign