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
JavaScript
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;