spyne
Version:
Reactive Real-DOM Framework for Advanced Javascript applications
89 lines (77 loc) • 2.97 kB
JavaScript
import { getAllMethodNames } from './frp-tools.js'
import { reject, curryN, __, map } from 'ramda'
export class SpyneTrait {
/**
* @module SpyneTrait
* @type extendable
* @param {this} parentContext
* @param {String} prefix
* @param {Boolean} autoInit
* @constructor
* @property {this} parentContent - = undefined; This binds all methods within SpyneTrait into the parentContext's object
* @property {String} prefix - = undefined; SpyneTraits forces all method names to begin with the same prefix. This allows other objects to quickly understand where the original method is set.
* @desc
* SpyneTraits allow the ehancing of classes and other objects without having to extend classes or manipulate function prototypes
*
*/
constructor(parentContext, prefix = '', autoInit = true) {
this.parentContext = parentContext
this.omittedMethods = [
'autoBinder',
'initAutoBinder',
'getEnhancerMethods',
'checkForMalformedMethods',
'caller',
'arguments',
'bindParentViewStream']
this.prefix = prefix
if (autoInit === true) {
this.autoBinder()
}
return this.allMethodsList
}
initAutoBinder() {
this.autoBinder()
}
getEnhancerMethods() {
return getAllMethodNames(this, this.omittedMethods)
}
checkForMalformedMethods(methodsArr) {
if (this.prefix === '') {
console.warn(`SPYNE WARNING: The following SpyneTrait ${this.constructor.name} needs a prefix`)
return
}
// let reStr = `^(${this.prefix})(.*)$`;
// let re = new RegExp(reStr);
const hasPrefix = (str) => str.indexOf(this.prefix) === 0
const malformedMethodsArr = reject(hasPrefix, methodsArr)
if (malformedMethodsArr.length >= 1) {
const warningStr = `Spyne Warning: The following method(s) in ${this.constructor.name} require the prefix, "${this.prefix}": [${malformedMethodsArr.join(', ')}];`
console.warn(warningStr)
}
}
bindParentViewStream(methodsObj, context) {
this.checkForMalformedMethods(methodsObj.allMethods)
const obj = {}
const bindMethodsToParentViewStream = (str, isStatic = false) => {
const constructorType = isStatic === true ? this.constructor : this
const propertyType = typeof (constructorType[str])
if (propertyType === 'function') {
obj[str] = context[str] = constructorType[str].bind(context)
}
}
const bindCurry = curryN(2, bindMethodsToParentViewStream)
const bindStaticMethodsToParentViewStream = bindCurry(__, true)
// MAP STATIC METHODS
map(bindStaticMethodsToParentViewStream, methodsObj.staticMethods)
// MAP MAIN METHODS
map(bindMethodsToParentViewStream, methodsObj.methods)
return obj
}
autoBinder() {
const allMethods = this.getEnhancerMethods()
// console.log('all ',allMethods);
this.allMethodsList = this.bindParentViewStream(allMethods, this.parentContext)
return this.allMethodsList
}
}