server/models/helpers/component-from-model.js
function(res, scContent, embedIn) {
      this.app = app;
      this.res = res;
      const self = this;
      let fields = [];
      if (scContent['fields']) {
        // already have fields
        fields = scContent['fields'];
      }
      else {
        // make fields from data
        let model = this._modelInfo(scContent['forModel']);
        _.forEach(model.prop, function(value, key) {
          // skip fields with a force value since they cannot modify
          if (scContent.forceVals && scContent.forceVals[key]) return;
          // skip exclude fields
          if (scContent.exclude && -1 !== scContent.exclude.indexOf(key)) return;
          // only include fields that we're told to
          if (scContent.include && -1 == scContent.include.indexOf(key)) return;
          // skip notForForm fields
          if (value.notForForm) return;
          // defaults
          let field = {
            label: (value.label)?value.label:key.replace(model.ns, ''),
            placeholder: value.placeholder,
            name: key,
            control: 'input',
            value: (value['default'])?value['default']:'',
            help: value['description'],
            format: value['format'],
            addons: value['addons'],
            embedIn: embedIn,
            validations: { },
            columns: (value.columns)?value.columns:null
          };
          // label should always propercase
          field.label = field.label.charAt(0).toUpperCase() + field.label.slice(1);
          // default is to use label as placeholder
          if (!field.placeholder) field.placeholder = field.label;
          // make Id column hidden
          if (value['id']){
            field.hidden = true;
            field.isId = true;
          }
          // other hidden fields
          if (scContent.hiddenFields && -1 !== scContent.hiddenFields.indexOf(key)){
            field.hidden = true;
          }
          if (value['enum']) {
            // controls for list items
            field.options = value['enum'];
            if (4 > value['enum'].length) field.control = 'radio';
            else field.control = 'select';
          }
          if (value['required']) {
            // required fields cannot be empty
            field.validations.allowEmpty = false;
          }
          if (value.format) {
            // format validation
            field.validations.format = value.format;
          }
          if (value.validation) {
            // add validations
            _.forEach(value.validation, function(val, k) {
              if ('type' == k && 'boolean' == val.value) {
                // for boolean, we show a single checkbox
                field.label = '';
                field.options = [value.label];
                field.control = 'checkbox';
                field.columns = 12;
                // prevents from assigning values as obj array
                field.boolean = true;
                // no need to assign as client-side validator
                return;
              }
              if (!field.validations.messages) field.validations.messages = {};
              field.validations[k] = val.value;
              if (val.message) field.validations['messages'][k] = val.message;
              // determin input size
              if ('input' == field.control && 'maxLength' == k) {
                if (val.value > 140) field.control = 'textarea';
                else if (val.value > 60) field.columns = 12;
              }
            });
          }
          // get embeded model props
          let embed = _.find(model.settings.relations, { type: 'embedsOne', property: key });
          if (embed) {
            let embedField = self.makeFormFields(res, {forModel: embed.model}, key);
            fields = fields.concat(embedField);
            return;
          }
          if (value.embedGetter) {
            // embed additional fields from theme/apps
            return _embedGetter(self, fields, value.embedGetter, key);
          }
          if (value.optionGetter) {
            // embed additional options from theme/apps
            _optionGetter(self, value.optionGetter, field.options, field);
          }
          // check for mixin
          if (scContent.fieldMixins && scContent.fieldMixins[key]) {
            let mixin = scContent.fieldMixins[key];
            if (mixin.eval) {
              // when mixin has script
              eval(mixin.eval);
            }
          }
          fields.push(field);
        });
      }
      return fields;
    }
function(res, scContent, embedIn) {
      this.app = app;
      this.res = res;
      const self = this;
      let fields = [];
      if (scContent['fields']) {
        // already have fields
        fields = scContent['fields'];
      }
      else {
        // make fields from data
        let model = this._modelInfo(scContent['forModel']);
        _.forEach(model.prop, function(value, key) {
          // skip fields with a force value since they cannot modify
          if (scContent.forceVals && scContent.forceVals[key]) return;
          // skip exclude fields
          if (scContent.exclude && -1 !== scContent.exclude.indexOf(key)) return;
          // only include fields that we're told to
          if (scContent.include && -1 == scContent.include.indexOf(key)) return;
          // skip notForForm fields
          if (value.notForForm) return;
          // defaults
          let field = {
            label: (value.label)?value.label:key.replace(model.ns, ''),
            placeholder: value.placeholder,
            name: key,
            control: 'input',
            value: (value['default'])?value['default']:'',
            help: value['description'],
            format: value['format'],
            addons: value['addons'],
            embedIn: embedIn,
            validations: { },
            columns: (value.columns)?value.columns:null
          };
          // label should always propercase
          field.label = field.label.charAt(0).toUpperCase() + field.label.slice(1);
          // default is to use label as placeholder
          if (!field.placeholder) field.placeholder = field.label;
          // make Id column hidden
          if (value['id']){
            field.hidden = true;
            field.isId = true;
          }
          // other hidden fields
          if (scContent.hiddenFields && -1 !== scContent.hiddenFields.indexOf(key)){
            field.hidden = true;
          }
          if (value['enum']) {
            // controls for list items
            field.options = value['enum'];
            if (4 > value['enum'].length) field.control = 'radio';
            else field.control = 'select';
          }
          if (value['required']) {
            // required fields cannot be empty
            field.validations.allowEmpty = false;
          }
          if (value.format) {
            // format validation
            field.validations.format = value.format;
          }
          if (value.validation) {
            // add validations
            _.forEach(value.validation, function(val, k) {
              if ('type' == k && 'boolean' == val.value) {
                // for boolean, we show a single checkbox
                field.label = '';
                field.options = [value.label];
                field.control = 'checkbox';
                field.columns = 12;
                // prevents from assigning values as obj array
                field.boolean = true;
                // no need to assign as client-side validator
                return;
              }
              if (!field.validations.messages) field.validations.messages = {};
              field.validations[k] = val.value;
              if (val.message) field.validations['messages'][k] = val.message;
              // determin input size
              if ('input' == field.control && 'maxLength' == k) {
                if (val.value > 140) field.control = 'textarea';
                else if (val.value > 60) field.columns = 12;
              }
            });
          }
          // get embeded model props
          let embed = _.find(model.settings.relations, { type: 'embedsOne', property: key });
          if (embed) {
            let embedField = self.makeFormFields(res, {forModel: embed.model}, key);
            fields = fields.concat(embedField);
            return;
          }
          if (value.embedGetter) {
            // embed additional fields from theme/apps
            return _embedGetter(self, fields, value.embedGetter, key);
          }
          if (value.optionGetter) {
            // embed additional options from theme/apps
            _optionGetter(self, value.optionGetter, field.options, field);
          }
          // check for mixin
          if (scContent.fieldMixins && scContent.fieldMixins[key]) {
            let mixin = scContent.fieldMixins[key];
            if (mixin.eval) {
              // when mixin has script
              eval(mixin.eval);
            }
          }
          fields.push(field);
        });
      }
      return fields;
    }
make fields list for Form Component from model