chain-able
Version:
interfaces that describe their intentions.
93 lines (85 loc) • 2.67 kB
JavaScript
const isUndefined = require('../deps/is/undefined')
const Chainable = require('../Chainable')
const ChainedMap = require('../ChainedMap')
const Observe = require('./Observe')
const Shorthands = require('./Shorthands')
const Transform = require('./Transform')
const DotProp = require('./DotProp')
const ComposableExtensions = [Observe, Shorthands, Transform, DotProp]
/**
* @desc compose chains all the way up from Chainable
* @since 3.0.0
*
* @param {Class | Function | undefined} [target=ChainedMap] class or function to extend
* @param {Array | undefined} [extensions=[Observe, Shorthands, Transform, DotProp]] Array of extensions to compose together left ro right
* @return {Class | Function} composed
*
* @tutorial examples/playground/compose
* @tutorial examples/babel/decorators
*
* @func compose
* @member compose
* @tests compose
* @types compose
* @symb 🎼
*
* @see https://formidable.com/blog/2017/infinite-state-composition-with-freactal/
* @see https://blog.javascripting.com/2016/02/02/encapsulation-in-redux/
* @see https://www.barbarianmeetscoding.com/blog/2016/01/04/safer-javascript-object-composition-with-traits-and-traits-dot-js/
* @see https://medium.com/javascript-scene/why-learn-functional-programming-in-javascript-composing-software-ea13afc7a257
* @see https://hackernoon.com/javascript-functional-composition-for-every-day-use-22421ef65a10
* @see https://github.com/stoeffel/awesome-fp-js
*
* @example
*
* class Eh extends compose() {}
* new Eh() instanceof Chainable
* //=> true
*
* @example
*
* class Target {}
* class Eh extends compose(Target) {}
* new Eh() instanceof Target
* //=> true
*
* @example
*
* class Target {}
* const mixin = SuperClass => class extends SuperClass {}
* class Eh extends compose(Target, ) {}
* new Eh() instanceof Chainable
* //=> true
*
* @example
*
* class Winning {}
* class Yes extends compose(Winning) {
* get winning() {
* return true
* }
* }
* const yes = new Yes()
* yes instanceof Winning && yes.winning
* //=> true
*
*/
function compose(target, extensions) {
let extend = isUndefined(extensions) ? ComposableExtensions : extensions
let composed = target
if (target && target instanceof Object) {
composed = ChainedMap.compose(Chainable.compose(target))
}
else {
composed = ChainedMap
}
for (let index = 0; index < extend.length; index++) {
composed = extend[index](composed) || composed || ChainedMap
}
return composed
}
compose.Observe = Observe
compose.Shorthands = Shorthands
compose.Transform = Transform
compose.DotProp = DotProp
module.exports = compose