UNPKG

class-o-mat

Version:

ALPHA VERSION ONLY: class-o-mats will help to create getter-setter functionality with validations that can be attached to a container class for easier coding. Some basic validations are included. class-o-mats also has the ability to store params as bloc

279 lines (225 loc) 8.61 kB
import Bunyan from 'bunyan'; const log = Bunyan.createLogger({name: "buildClass"}); import mixin from 'mixin-decorator'; import merger from 'lodash.merge'; import NamedDepCounter from 'named-dep-counter'; import { NONE } from '../constants/types'; const buildFieldMixins =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { key, fieldOMats, paramKeyPrefix, paramObjectKey, ON_GET, ON_SET, } = params; if (ON_GET !== NONE) { fieldOMats.forEach((field)=>{ field._appendEvent(ON_GET, key, 'ON_GET') }); } if (ON_SET !== NONE) { fieldOMats.forEach((field)=>field._appendEvent(ON_SET, key, 'ON_SET')); } const ___fields = []; const required = []; fieldOMats.forEach((fieldOMat)=>{ const {key, _default, isRequired} = fieldOMat._params; ___fields.push(key); if (isRequired === true) { required.push(key); fieldOMat.onSet((self, key, value)=>{ self.___markReady(key) }); } mixins = fieldOMat.addToClassMixins( mixins, paramObjectKey, paramKeyPrefix ); defaults[fieldOMat._params.key] = fieldOMat._params._default; }); if (required.length !== 0) { const depCounter = new NamedDepCounter(`${key}_required`); depCounter.deps(required); mixins.___required = function() { depCounter.self(this); this.___required = function() { return depCounter }; return depCounter; }; mixins.___ready = function() { depCounter.self(this); this.___ready = function() { return depCounter.ready()} return depCounter.ready(); } mixins.___markReady = function(key) { depCounter.self(this); this.___markReady = function(key) { return depCounter.mark(key)} depCounter.mark(key); } } mixins.___fields = ___fields; return [{classOMat, mixins, defaults, params}, buildMethods] } const buildParamObjectAccessor =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { paramObjectKey } = params; if (paramObjectKey === false) return {classOMat, mixins, defaults, params}; if(paramObjectKey !== false) { mixins[paramObjectKey.slice(1)] = function(params=NONE, merge = NONE){ const thisParams = this[paramObjectKey]; if (params===NONE) return thisParams; this[paramObjectKey] = ( merge === NONE) ? params : (merge === true) ? { ...params, ...thisParams } : { ...thisParams, ...params} return this; } } return [{ classOMat, mixins, defaults, params}, buildMethods]; } const buildNestingAccessors =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { paramObjectKey } = params; const getChildren = (paramObjectKey === false) ? (self)=>self.___children : (self)=>self[paramObjectKey].___children; const setChildren = (paramObjectKey === false) ? (self, value)=>self.___children = value : (self, value)=>self[paramObjectKey].___children = value; defaults.___children = {}; mixins.___children = function(){ return getChildren(this) } mixins.___child = function(key = NONE) { const ___children = getChildren(this); if (___children === undefined) return false; if (key === NONE) return ___children; return ( key in ___children === true) ? ___children[key] : false; } mixins.___deleteChild = function(key = NONE) { const ___children = getChildren(this); if (key === NONE || key in ___children === false) { setChildren(this, {}); return true; } delete ___children[key]; setChildren(this, ___children); return true; } return [{ classOMat, mixins, defaults, params}, buildMethods]; } const buildKeysAccessor =({classOMat, mixins, defaults, params}, buildMethods)=>{ if (params.createKeysAccessor !== true) return { classOMat, mixins, defaults, params}; const keys = params.fieldOMats.map((fieldOMat)=>fieldOMat.key()); mixins.keys = function() { return keys }; return [{ classOMat, mixins, defaults, params }, buildMethods]; } const buildConstructorNoParamsObject =({classOmat, mixins, defaults, params}, buildMethods)=>{ const { key, uid } = params; mixins.constructor = function(...p) { this.___uid = uid; this.___minionKey = key; const defaultKeys = Object.keys(defaults); defaultKeys.forEach((key)=>{ const v = defaults[key]; this['___'+key] = typeof v === 'object' ? clonedeep(v) : v; } ); } return [{ classOMat, mixins, defaults, params }, buildMethods]; } const buildConstructorParamsObject =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { key, paramObjectKey, uid } = params; mixins.constructor = function(...p) { this.___uid = uid; this.___minionKey = key; this[paramObjectKey] = merger({}, defaults, this[paramObjectKey]||{}); } return [{classOMat, mixins, defaults, params}, buildMethods]; } const buildConstructor =({classOMat, mixins, defaults, params}, buildMethods)=>{ return (params.paramObjectKey === false) ? buildMethods.buildConstructorNoParamsObject( {classOMat, mixins, defaults, params}, buildMethods ) : buildMethods.buildConstructorParamsObject( {classOMat, mixins, defaults, params}, buildMethods ); } const buildClass =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { BaseClass, key, paramObjectKey, uid } = params; let workingArguments; [workingArguments, buildMethods] = buildMethods.buildConstructor( {classOMat, mixins, defaults, params}, buildMethods ); const { constructor, ___fields, ...workingMixins } = workingArguments.mixins; @mixin(workingMixins) class WorkingClass extends BaseClass { ___fields = ___fields; constructor(...p) { super(...p); constructor.call(this, ...p); } } return [WorkingClass, buildMethods]; } const buildMixins =({classOMat, mixins, defaults, params}, buildMethods)=>{ const { cacheOMats, classOMatGroup, childOMatInfos, needsParentAccessor, paramObjectKey, parentKey } = params; let workingArguments; mixins.___classGroup = function() {return classGroup}; if (Object.keys(childOMatInfos).length !==0) { [workingArguments, buildMethods] = buildMethods.buildNestingAccessors( {classOMat, mixins, defaults, params}, buildMethods ); } else { workingArguments = {classOMat, mixins, defaults, params}; } if (cacheOMats === true) { workingArguments.mixins.___classOMats = function() { return clasSOMatGroup; }; } [workingArguments, buildMethods] = buildMethods.buildParamObjectAccessor(workingArguments, buildMethods); [workingArguments, buildMethods] = buildMethods.buildKeysAccessor(workingArguments, buildMethods); return [workingArguments, buildMethods]; } const build =({classOMat, mixins, defaults, params}, buildMethods)=> { if (params.needsParentAccessor === true || 1===1) { classOMat.field(params.parentKey); } let workingArguments; [workingArguments, buildMethods] = buildMethods.buildFieldMixins({classOMat, mixins, defaults, params}, buildMethods); [workingArguments, buildMethods] = buildMethods.buildMixins(workingArguments, buildMethods); return buildClass(workingArguments, buildMethods); } const buildClassMethods = { build, buildKeysAccessor, buildClass, buildConstructor, buildConstructorParamsObject, buildConstructorNoParamsObject, buildFieldMixins, buildMixins, buildNestingAccessors, buildParamObjectAccessor }; export default buildClassMethods;