import { inlineCalculationFieldToCompute, computedOnlyInlineCalculationField, } from '/imports/api/properties/subSchemas/inlineCalculationField.js'; import { fieldToCompute, computedOnlyField, } from '/imports/api/properties/subSchemas/computedField.js'; import SimpleSchema from 'simpl-schema'; // Search through the schema for keys whose type is 'fieldToCompute' etc. // replace the type with Object and attach extend the schema with // the required fields to make the computation work export default function createPropertySchema(definition){ const computationFields = { inlineCalculationFieldToCompute: [], computedOnlyInlineCalculationField: [], fieldToCompute: [], computedOnlyField: [], }; const computedKeys = Object.keys(computationFields); for (let key in definition){ const def = definition[key]; if (computedKeys.includes(def.type)){ computationFields[def.type].push(key); applyDefaultCalculationValue(definition, key); def.type = Object; if (!def.optional){ console.warn( `computed field: '${key}' of '${def.type}' is expected to be optional` ); } if (def.removeBeforeCompute){ console.warn( `computed field: '${key}' of '${def.type}' should not be removed before computation` ) } } } // Create a schema with the edited definition const schema = new SimpleSchema(definition); // Extend the schema with all the computation fields computationFields.inlineCalculationFieldToCompute.forEach(key => { schema.extend(inlineCalculationFieldToCompute(key)) }); computationFields.computedOnlyInlineCalculationField.forEach(key => { schema.extend(computedOnlyInlineCalculationField(key)) }); computationFields.fieldToCompute.forEach(key => { schema.extend(fieldToCompute(key)) }); computationFields.computedOnlyField.forEach(key => { schema.extend(computedOnlyField(key)) }); return schema } function applyDefaultCalculationValue(definition, key){ const def = definition[key]; if ( def.type === 'computedOnlyField' || def.type === 'computedOnlyInlineCalculationField' ){ // don't apply defaults to computed only fields // because it would add the calculation field which should only appear // on the fields to compute return; } let defaultValue = def.defaultValue; if (!defaultValue) return; let calcField; if (def.type === 'fieldToCompute'){ calcField = key + '.calculation' } else { calcField = key + '.text' } if (definition[calcField]){ definition[calcField].defaultValue = defaultValue; } else { definition[calcField] = { type: String, defaultValue, optional: true, }; } delete def.defaultValue; }