code: function fillForProperties(data, props, objTemplate, filter) {
  
    if (!Array.isArray(data)) {
      throw new TypeError('data should be an array');
    }
  
    if (!Array.isArray(props)) {
      throw new TypeError('props should be an array');
    }
  
    var d = data.slice();
    var missing = missingCombinations(d, props);
    missing.forEach(item => {
      var obj = _.cloneDeep(objTemplate);
      var index = 0;
      item.forEach(item => {
        obj[props[index].key] = item;
        index++;
      });
      d.push(obj);
      return true;
    });
  
    if (filter) {
      return d.filter(item => {
        var dontInclude = false;
        props.forEach(prop => {
          if (prop.valueRange.indexOf(item[prop.key]) == -1) {
            dontInclude = true;
          }
        });
        return !dontInclude;
      });
    }
    return d;
  }
docs: /*
  Make sure data array has entries for all
  combinations of specified property values,
  filling the array with new entries if necessary.
  
  @param {Array} props - array of property definitions which are
  expected to exist. Each object in the array has
  the following attributes:
  
  key - data object attribute name
  valueRange - range of values expected for key
  
  @param {Object} objTemplate - template for new entries
  
  @param {bool} filter - set to true to filter out any entries