2019-07-19 13:52:08 +02:00
|
|
|
import {
|
|
|
|
isString,
|
2019-08-04 23:21:16 +02:00
|
|
|
isUndefined,
|
|
|
|
find,
|
|
|
|
keys,
|
|
|
|
uniq,
|
|
|
|
some,
|
|
|
|
keyBy
|
2019-07-19 13:52:08 +02:00
|
|
|
} from "lodash/fp";
|
2019-07-19 19:03:58 +02:00
|
|
|
import { types } from "./types";
|
2019-07-19 13:52:08 +02:00
|
|
|
import { assign } from "lodash";
|
2019-08-04 23:21:16 +02:00
|
|
|
import { pipe } from "../../common/core";
|
|
|
|
import { isRootComponent } from "./searchComponents";
|
|
|
|
|
|
|
|
export const createPropDefinitionForDerived = (allComponents, componentName) => {
|
|
|
|
const traverseForProps = (cname, derivedProps=[]) => {
|
|
|
|
const component = find(c => c.name === cname)(allComponents);
|
|
|
|
if(isRootComponent(component)) return ({propDef:component.props, derivedProps});
|
|
|
|
return traverseForProps(component.inherits, [component.props, ...derivedProps]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const {propDef, derivedProps} = traverseForProps(componentName);
|
|
|
|
|
|
|
|
const hasDerivedProp = k => pipe(derivedProps, [
|
|
|
|
keys,
|
|
|
|
uniq,
|
|
|
|
some(key => key === k)
|
|
|
|
]);
|
|
|
|
|
|
|
|
return pipe(propDef, [
|
|
|
|
keys,
|
|
|
|
filter(k => !hasDerivedProp(k)),
|
|
|
|
reduce((obj, k) => {
|
|
|
|
obj[k] = propDef[k]
|
|
|
|
}, {})
|
|
|
|
])
|
|
|
|
}
|
2019-07-19 13:52:08 +02:00
|
|
|
|
2019-07-20 22:41:06 +02:00
|
|
|
export const createProps = (componentName, propsDefinition, derivedFromProps) => {
|
|
|
|
|
|
|
|
const error = (propName, error) =>
|
|
|
|
errors.push({propName, error});
|
|
|
|
|
|
|
|
const props = {
|
|
|
|
_component: componentName
|
|
|
|
};
|
2019-07-19 13:52:08 +02:00
|
|
|
|
|
|
|
const errors = [];
|
|
|
|
|
2019-07-20 22:41:06 +02:00
|
|
|
if(!componentName)
|
|
|
|
error("_component", "Component name not supplied");
|
|
|
|
|
2019-07-19 13:52:08 +02:00
|
|
|
for(let propDef in propsDefinition) {
|
|
|
|
const parsedPropDef = parsePropDef(propsDefinition[propDef]);
|
|
|
|
if(parsedPropDef.error)
|
2019-07-20 22:41:06 +02:00
|
|
|
error(propDef, parsedPropDef.error);
|
2019-07-19 13:52:08 +02:00
|
|
|
else
|
|
|
|
props[propDef] = parsedPropDef;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(derivedFromProps) {
|
|
|
|
assign(props, ...derivedFromProps);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ({
|
|
|
|
props, errors
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const parsePropDef = propDef => {
|
2019-07-19 19:03:58 +02:00
|
|
|
const error = message => ({error:message, propDef});
|
2019-07-19 13:52:08 +02:00
|
|
|
|
|
|
|
if(isString(propDef)) {
|
|
|
|
if(!types[propDef])
|
|
|
|
return error(`Do not recognise type ${propDef}`);
|
|
|
|
|
|
|
|
return types[propDef].default();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!propDef.type)
|
|
|
|
return error("Property Definition must declare a type");
|
|
|
|
|
|
|
|
const type = types[propDef.type];
|
|
|
|
if(!type)
|
|
|
|
return error(`Do not recognise type ${propDef.type}`);
|
|
|
|
|
|
|
|
if(isUndefined(propDef.default))
|
|
|
|
return type.default(propDef);
|
|
|
|
|
|
|
|
if(!type.isOfType(propDef.default))
|
|
|
|
return error(`${propDef.default} is not of type ${type}`);
|
|
|
|
|
|
|
|
return propDef.default;
|
|
|
|
}
|
|
|
|
|
2019-07-19 19:03:58 +02:00
|
|
|
/*
|
|
|
|
Allowed propDefOptions
|
|
|
|
- type: string, bool, number, array
|
|
|
|
- default: default value, when undefined
|
|
|
|
- required: field is required
|
|
|
|
*/
|