"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getRecordGroupOptionListName = exports.getRecordFieldOptionListName = exports.getFirstColumnName = exports.findVocabularyUses = exports.findFieldConfigInPart = exports.findField = exports.getDefaultSearchVocabulary = exports.getDefaultSearchRecordType = exports.validateLocation = exports.isUtility = exports.isAuthority = exports.getRequiredMessage = exports.getFieldComputer = exports.getFieldCustomValidator = exports.getFieldDataType = exports.isFieldRequired = exports.isFieldRepeating = exports.isFieldCloneable = exports.getStickyFields = exports.getDefaults = exports.getDefaultValue = exports.getVocabularyConfigByServicePath = exports.getVocabularyConfigByShortID = exports.getRecordTypeNameByUri = exports.getRecordTypeConfigByUri = exports.getRecordTypeConfigByServicePath = exports.getRecordTypeNameByServiceObjectName = exports.getRecordTypeConfigByServiceObjectName = exports.getRecordTypeConfigByServiceDocumentName = exports.initConfig = exports.mergeConfig = exports.mergeStrategy = exports.applyPlugins = exports.applyPlugin = exports.evaluatePlugin = exports.finalizeRecordTypes = exports.initializeRecordTypes = exports.initializeExtensionFieldParents = exports.initializeExtensions = exports.dataPathToFieldDescriptorPath = exports.mergeKey = exports.configKey = void 0;

var _react = _interopRequireDefault(require("react"));

var _immutable = _interopRequireDefault(require("immutable"));

var _mergeWith = _interopRequireDefault(require("lodash/mergeWith"));

var _flatMap = _interopRequireDefault(require("lodash/flatMap"));

var _get = _interopRequireDefault(require("lodash/get"));

var _set = _interopRequireDefault(require("lodash/set"));

var _warning = _interopRequireDefault(require("warning"));

var _errorCodes = require("../constants/errorCodes");

var _dataTypes = require("../constants/dataTypes");

var _blobHelpers = require("./blobHelpers");

var _formatHelpers = require("./formatHelpers");

var _recordDataHelpers = require("./recordDataHelpers");

var _csidHelpers = require("./csidHelpers");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const onlyDigitsPattern = /^\d+$/;

const isNotNumeric = string => !onlyDigitsPattern.test(string);

const configKey = '[config]';
exports.configKey = configKey;
const mergeKey = '[merge]';
exports.mergeKey = mergeKey;

const dataPathToFieldDescriptorPath = dataPath => dataPath.filter(isNotNumeric);
/*
 * Initialize the extension configurations in a configuration object. This function mutates the
 * argument configuration.
 *
 * - Set the extensionName property of each top level field in the extension to the extension name
 */


exports.dataPathToFieldDescriptorPath = dataPathToFieldDescriptorPath;

const initializeExtensions = config => {
  const {
    extensions
  } = config;

  if (extensions) {
    Object.keys(extensions).forEach(extensionName => {
      const extension = extensions[extensionName];
      const {
        fields
      } = extension;

      if (fields) {
        Object.values(fields).forEach(fieldDescriptor => {
          (0, _set.default)(fieldDescriptor, [configKey, 'extensionName'], extensionName);
        });
      }
    });
  }

  return config;
};

exports.initializeExtensions = initializeExtensions;

const initializeExtensionFieldParents = fieldDescriptor => {
  if (fieldDescriptor) {
    Object.keys(fieldDescriptor).filter(key => key !== configKey).forEach(key => {
      const childFieldDescriptor = fieldDescriptor[key];
      const isExtensionField = (0, _get.default)(childFieldDescriptor, [configKey, 'extensionName']);

      if (isExtensionField) {
        // Make a copy of this field descriptor and its configuration, so that different
        // configuration can be applied to each use of the extension (really wishing I'd made the
        // config an Immutable, so explicit copy wouldn't be necessary).
        // Set the extension parent config in the extension field's config.
        const childFieldDescriptorCopy = Object.assign({}, childFieldDescriptor, {
          [configKey]: Object.assign({}, childFieldDescriptor[configKey], {
            extensionParentConfig: fieldDescriptor[configKey]
          })
        }); // eslint-disable-next-line no-param-reassign

        fieldDescriptor[key] = childFieldDescriptorCopy;
      } else {
        initializeExtensionFieldParents(childFieldDescriptor);
      }
    });
  }
};
/*
 * Initialize the record type configurations in a configuration object. This function mutates the
 * argument configuration.
 *
 * - Set the name property of each recordTypes entry to its key
 * - Set the name property of each vocabularies entry to its key
 * - Set the parent property of any extension fields
 */


exports.initializeExtensionFieldParents = initializeExtensionFieldParents;

const initializeRecordTypes = config => {
  const keys = ['recordTypes', ['invocables', 'report'], ['invocables', 'batch']];
  keys.forEach(key => {
    const recordTypesConfig = (0, _get.default)(config, key);

    if (recordTypesConfig) {
      Object.keys(recordTypesConfig).forEach(recordTypeName => {
        const recordType = recordTypesConfig[recordTypeName];
        recordType.name = recordTypeName;
        const {
          fields,
          vocabularies
        } = recordType;

        if (fields) {
          Object.values(fields).forEach(fieldDescriptor => {
            initializeExtensionFieldParents(fieldDescriptor);
          });
        }

        if (vocabularies) {
          Object.keys(vocabularies).forEach(vocabularyName => {
            vocabularies[vocabularyName].name = vocabularyName;
          });
        }
      });
    }
  });
  return config;
};
/*
 * Finalize the record type configurations in a configuration object. This function mutates the
 * argument configuration.
 *
 * - Delete any record type or vocabulary that is disabled
 */


exports.initializeRecordTypes = initializeRecordTypes;

const finalizeRecordTypes = config => {
  const {
    recordTypes
  } = config;

  if (recordTypes) {
    Object.keys(recordTypes).forEach(recordTypeName => {
      const recordType = recordTypes[recordTypeName];

      if (recordType.disabled) {
        delete recordTypes[recordTypeName];
      } else {
        const {
          vocabularies
        } = recordType;

        if (vocabularies) {
          Object.keys(vocabularies).forEach(vocabularyName => {
            const vocabulary = vocabularies[vocabularyName];

            if (vocabulary.disabled) {
              delete vocabularies[vocabularyName];
            }
          });
        }
      }
    });
  }

  return config;
};

exports.finalizeRecordTypes = finalizeRecordTypes;

const evaluatePlugin = (plugin, configContext) => {
  const pluginType = typeof plugin;
  const isValidType = plugin && (pluginType === 'function' || pluginType === 'object' && !Array.isArray(plugin));
  process.env.NODE_ENV !== "production" ? (0, _warning.default)(isValidType, 'A plugin must be an object or a function.') : void 0;

  if (!isValidType) {
    return {};
  }

  const config = pluginType === 'object' ? plugin : plugin(configContext);
  initializeExtensions(config);
  initializeRecordTypes(config);
  return config;
};

exports.evaluatePlugin = evaluatePlugin;

const applyPlugin = function applyPlugin(targetConfig, plugin) {
  let configContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  const pluginConfigContribution = evaluatePlugin(plugin, configContext);
  /* Gotta do this mutual recursion */

  /* eslint-disable no-use-before-define */

  return mergeConfig(targetConfig, pluginConfigContribution, configContext);
  /* eslint-enable no-use-before-define */
};

exports.applyPlugin = applyPlugin;

const applyPlugins = function applyPlugins(targetConfig, plugins) {
  let configContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  const isArray = Array.isArray(plugins);
  process.env.NODE_ENV !== "production" ? (0, _warning.default)(isArray, 'Plugins must be an array.') : void 0;

  if (!isArray) {
    return targetConfig;
  }

  return plugins.reduce((updatedConfig, plugin) => {
    // eslint-disable-next-line no-param-reassign
    configContext.config = updatedConfig;
    return applyPlugin(updatedConfig, plugin, configContext);
  }, targetConfig);
};

exports.applyPlugins = applyPlugins;
const mergeStrategy = {
  override: srcValue => Object.assign({}, srcValue, {
    [mergeKey]: 'override'
  })
};
exports.mergeStrategy = mergeStrategy;

const configMerger = (objValue, srcValue, key) => {
  if (Array.isArray(objValue)) {
    // Don't merge arrays. Just override with the source value.
    return srcValue;
  }

  if (key === 'advancedSearch') {
    // Don't merge advanced search config. Just override with the source value.
    return srcValue;
  }

  if (_react.default.isValidElement(objValue)) {
    // Don't merge React elements, e.g. in form templates. Just override with the source value.
    return srcValue;
  }

  if (srcValue && typeof srcValue === 'object' && srcValue[mergeKey] === 'override') {
    const srcValueCopy = Object.assign({}, srcValue);
    delete srcValueCopy[mergeKey];
    return srcValueCopy;
  }

  return undefined;
};

const mergeConfig = function mergeConfig(targetConfig, sourceConfig) {
  let configContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  // eslint-disable-next-line no-param-reassign
  configContext.config = targetConfig;
  const pluginsAppliedConfig = sourceConfig && 'plugins' in sourceConfig ? applyPlugins(targetConfig, sourceConfig.plugins, configContext) : targetConfig;
  const mergedConfig = (0, _mergeWith.default)({}, pluginsAppliedConfig, sourceConfig, configMerger);
  delete mergedConfig.plugins;
  return mergedConfig;
};

exports.mergeConfig = mergeConfig;

const initConfig = (config, configContext) => mergeConfig({}, config, configContext);

exports.initConfig = initConfig;

const getRecordTypeConfigByServiceDocumentName = (config, documentName) => {
  if (!documentName) {
    return undefined;
  }

  if (!config.recordTypesByServiceDocumentName) {
    const recordTypesByServiceDocumentName = {};
    const {
      recordTypes
    } = config;
    Object.keys(recordTypes).forEach(recordType => {
      const recordTypeConfig = recordTypes[recordType];
      const {
        serviceConfig
      } = recordTypeConfig;
      recordTypesByServiceDocumentName[serviceConfig.documentName] = recordTypeConfig;
    });
    /* eslint-disable no-param-reassign */

    config.recordTypesByServiceDocumentName = recordTypesByServiceDocumentName;
    /* eslint-enable no-param-reassign */
  }

  return config.recordTypesByServiceDocumentName[documentName];
};

exports.getRecordTypeConfigByServiceDocumentName = getRecordTypeConfigByServiceDocumentName;

const getRecordTypeConfigByServiceObjectName = (config, objectName) => {
  if (!objectName) {
    return undefined;
  }

  if (!config.recordTypesByServiceObjectName) {
    const recordTypesByServiceObjectName = {};
    const {
      recordTypes
    } = config;
    Object.keys(recordTypes).forEach(recordType => {
      const recordTypeConfig = recordTypes[recordType];
      recordTypesByServiceObjectName[recordTypeConfig.serviceConfig.objectName] = recordTypeConfig;
    });
    /* eslint-disable no-param-reassign */

    config.recordTypesByServiceObjectName = recordTypesByServiceObjectName;
    /* eslint-enable no-param-reassign */
  }

  return config.recordTypesByServiceObjectName[objectName];
};

exports.getRecordTypeConfigByServiceObjectName = getRecordTypeConfigByServiceObjectName;

const getRecordTypeNameByServiceObjectName = (config, objectName) => {
  const recordTypeConfig = getRecordTypeConfigByServiceObjectName(config, objectName);
  return recordTypeConfig ? recordTypeConfig.name : undefined;
};

exports.getRecordTypeNameByServiceObjectName = getRecordTypeNameByServiceObjectName;

const getRecordTypeConfigByServicePath = (config, servicePath) => {
  if (!servicePath) {
    return undefined;
  }

  if (!config.recordTypesByServicePath) {
    const recordTypesByServicePath = {};
    const {
      recordTypes
    } = config;
    Object.keys(recordTypes).forEach(recordType => {
      const recordTypeConfig = recordTypes[recordType];
      recordTypesByServicePath[recordTypeConfig.serviceConfig.servicePath] = recordTypeConfig;
    });
    /* eslint-disable no-param-reassign */

    config.recordTypesByServicePath = recordTypesByServicePath;
    /* eslint-enable no-param-reassign */
  }

  return config.recordTypesByServicePath[servicePath];
};

exports.getRecordTypeConfigByServicePath = getRecordTypeConfigByServicePath;

const getRecordTypeConfigByUri = (config, uri) => {
  if (!uri) {
    return undefined;
  }

  const servicePath = uri.split('/', 2)[1];
  return getRecordTypeConfigByServicePath(config, servicePath);
};

exports.getRecordTypeConfigByUri = getRecordTypeConfigByUri;

const getRecordTypeNameByUri = (config, uri) => {
  const recordTypeConfig = getRecordTypeConfigByUri(config, uri);
  return recordTypeConfig ? recordTypeConfig.name : undefined;
};

exports.getRecordTypeNameByUri = getRecordTypeNameByUri;

const getVocabularyConfigByShortID = (recordTypeConfig, shortID) => {
  if (!shortID) {
    return undefined;
  }

  if (!recordTypeConfig.vocabulariesByShortID) {
    const vocabulariesByShortID = {};
    const {
      vocabularies
    } = recordTypeConfig;

    if (vocabularies) {
      Object.keys(vocabularies).forEach(vocabulary => {
        const vocabularyConfig = vocabularies[vocabulary];
        const {
          servicePath
        } = vocabularyConfig.serviceConfig;

        if (servicePath && servicePath.indexOf('urn:cspace:name(') === 0 && servicePath.lastIndexOf(')') === servicePath.length - 1) {
          const vocabularyShortID = servicePath.substring(16, servicePath.length - 1);
          vocabulariesByShortID[vocabularyShortID] = vocabularyConfig;
        }
      });
      /* eslint-disable no-param-reassign */

      recordTypeConfig.vocabulariesByShortID = vocabulariesByShortID;
      /* eslint-enable no-param-reassign */
    }
  }

  return recordTypeConfig.vocabulariesByShortID[shortID];
};

exports.getVocabularyConfigByShortID = getVocabularyConfigByShortID;
const vocabularyServicePathPattern = /^urn:cspace:name\((.*?)\)$/;

const getVocabularyConfigByServicePath = (recordTypeConfig, servicePath) => {
  const match = vocabularyServicePathPattern.exec(servicePath);

  if (!match) {
    return undefined;
  }

  const shortID = match[1];
  return getVocabularyConfigByShortID(recordTypeConfig, shortID);
};

exports.getVocabularyConfigByServicePath = getVocabularyConfigByServicePath;

const getDefaultValue = fieldDescriptor => {
  const config = fieldDescriptor[configKey];

  if (config) {
    const {
      dataType,
      defaultValue
    } = config;

    if (typeof defaultValue === 'object' && !_immutable.default.Map.isMap(defaultValue)) {
      // If an object is supplied as a default value, convert it to an immutable map.
      return _immutable.default.fromJS(defaultValue);
    } else if (typeof defaultValue === 'undefined' && dataType === _dataTypes.DATA_TYPE_BOOL) {
      // If no default value is configured for a boolean field, consider it to be false.
      return false;
    }

    return defaultValue;
  }

  return undefined;
};

exports.getDefaultValue = getDefaultValue;

const getDefaults = function getDefaults(fieldDescriptor) {
  let currentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  let results = [];
  const defaultValue = getDefaultValue(fieldDescriptor);

  if (typeof defaultValue !== 'undefined') {
    results = results.concat({
      path: currentPath,
      value: defaultValue
    });
  }

  const childKeys = Object.keys(fieldDescriptor).filter(key => key !== configKey);
  childKeys.forEach(childKey => {
    const childPath = currentPath.concat(childKey);
    const childfieldDescriptor = fieldDescriptor[childKey];
    const childResults = getDefaults(childfieldDescriptor, childPath);
    results = results.concat(childResults);
  });
  return results;
};
/**
 * Returns an array of paths to sticky fields that exist under a given field.
 */


exports.getDefaults = getDefaults;

const getStickyFields = function getStickyFields(fieldDescriptor) {
  let currentPath = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

  if (!fieldDescriptor) {
    return [];
  }

  const isSticky = (0, _get.default)(fieldDescriptor, [configKey, 'sticky']);

  if (isSticky) {
    return [currentPath];
  }

  return Object.keys(fieldDescriptor).filter(key => key !== configKey).reduce((results, childKey) => {
    const childPath = currentPath.concat(childKey);
    const childfieldDescriptor = fieldDescriptor[childKey];
    const childResults = getStickyFields(childfieldDescriptor, childPath);
    return results.concat(childResults);
  }, []);
};

exports.getStickyFields = getStickyFields;

const isFieldCloneable = fieldDescriptor => {
  const config = fieldDescriptor[configKey];

  if (config && 'cloneable' in config) {
    return config.cloneable;
  }

  return true;
};

exports.isFieldCloneable = isFieldCloneable;

const isFieldRepeating = fieldDescriptor => {
  const config = fieldDescriptor[configKey];

  if (config && 'repeating' in config) {
    return config.repeating;
  }

  return false;
};

exports.isFieldRepeating = isFieldRepeating;

const isFieldRequired = (fieldDescriptor, recordData) => {
  const required = (0, _get.default)(fieldDescriptor, [configKey, 'required']);
  return !!(typeof required === 'function' ? required(recordData) : required);
};

exports.isFieldRequired = isFieldRequired;

const getFieldDataType = fieldDescriptor => {
  let type;
  const fieldConfig = fieldDescriptor[configKey];

  if (fieldConfig) {
    type = fieldConfig.dataType;
  }

  if (!type) {
    // Check if there are child field descriptors. If so, default to map.
    const keys = Object.keys(fieldDescriptor);

    for (let i = 0; i < keys.length; i += 1) {
      if (keys[i] !== configKey) {
        type = _dataTypes.DATA_TYPE_MAP;
        break;
      }
    }
  }

  if (!type) {
    // Default to string.
    type = _dataTypes.DATA_TYPE_STRING;
  }

  return type;
};

exports.getFieldDataType = getFieldDataType;

const getFieldCustomValidator = fieldDescriptor => {
  let validator;
  const fieldConfig = fieldDescriptor[configKey];

  if (fieldConfig) {
    validator = fieldConfig.validate;
  }

  return validator;
};

exports.getFieldCustomValidator = getFieldCustomValidator;

const getFieldComputer = fieldDescriptor => {
  let computer;
  const fieldConfig = fieldDescriptor[configKey];

  if (fieldConfig) {
    computer = fieldConfig.compute;
  }

  return computer;
};

exports.getFieldComputer = getFieldComputer;

const getRequiredMessage = fieldDescriptor => (0, _get.default)(fieldDescriptor, [configKey, 'messages', 'required']);

exports.getRequiredMessage = getRequiredMessage;

const isAuthority = recordTypeConfig => (0, _get.default)(recordTypeConfig, ['serviceConfig', 'serviceType']) === 'authority';

exports.isAuthority = isAuthority;

const isUtility = recordTypeConfig => (0, _get.default)(recordTypeConfig, ['serviceConfig', 'serviceType']) === 'utility';

exports.isUtility = isUtility;

const validateLocation = (config, location) => {
  const {
    recordType,
    vocabulary,
    csid,
    subresource,
    relatedRecordType,
    relatedCsid
  } = location;
  const recordTypeConfig = (0, _get.default)(config, ['recordTypes', recordType]);

  if (!recordTypeConfig || recordTypeConfig.disabled) {
    return {
      error: {
        recordType,
        code: _errorCodes.ERR_UNKNOWN_RECORD_TYPE
      }
    };
  }

  if (isAuthority(recordTypeConfig)) {
    if (!vocabulary) {
      return {
        error: {
          recordType,
          code: _errorCodes.ERR_MISSING_VOCABULARY
        }
      };
    }

    const vocabularyConfig = (0, _get.default)(recordTypeConfig, ['vocabularies', vocabulary]);

    if (!vocabularyConfig || vocabularyConfig.disabled) {
      return {
        error: {
          recordType,
          vocabulary,
          code: _errorCodes.ERR_UNKNOWN_VOCABULARY
        }
      };
    }
  } else if (vocabulary) {
    return {
      error: {
        recordType,
        vocabulary,
        code: _errorCodes.ERR_UNKNOWN_VOCABULARY
      }
    };
  }

  if (csid && !(0, _csidHelpers.isCsid)(csid) && !(0, _csidHelpers.isUrnCsid)(csid)) {
    return {
      error: {
        csid,
        code: _errorCodes.ERR_INVALID_CSID
      }
    };
  }

  if (subresource) {
    const subresourceConfig = (0, _get.default)(config, ['subresources', subresource]);

    if (!subresourceConfig) {
      return {
        error: {
          subresource,
          code: _errorCodes.ERR_UNKNOWN_SUBRESOURCE
        }
      };
    }
  }

  if (relatedRecordType) {
    const serviceType = (0, _get.default)(recordTypeConfig, ['serviceConfig', 'serviceType']);
    const relatedServiceType = (0, _get.default)(config, ['recordTypes', relatedRecordType, 'serviceConfig', 'serviceType']);

    if (serviceType !== 'procedure' && serviceType !== 'object' || relatedServiceType !== 'procedure' && relatedServiceType !== 'object') {
      return {
        error: {
          recordType,
          relatedRecordType,
          code: _errorCodes.ERR_INVALID_RELATED_TYPE
        }
      };
    }
  }

  if (relatedCsid && !(0, _csidHelpers.isCsid)(relatedCsid)) {
    return {
      error: {
        csid: relatedCsid,
        code: _errorCodes.ERR_INVALID_CSID
      }
    };
  }

  return {};
};

exports.validateLocation = validateLocation;

const getDefaultSearchRecordType = config => {
  const {
    recordTypes
  } = config;
  const names = Object.keys(recordTypes);
  let defaultSearchRecordType;

  for (let i = 0; i < names.length; i += 1) {
    const name = names[i];

    if (recordTypes[name].defaultForSearch) {
      defaultSearchRecordType = name;
      break;
    }
  }

  return defaultSearchRecordType || names[0];
};

exports.getDefaultSearchRecordType = getDefaultSearchRecordType;

const getDefaultSearchVocabulary = recordTypeConfig => {
  const {
    vocabularies
  } = recordTypeConfig;
  const names = Object.keys(vocabularies);
  let defaultSearchVocabulary;

  for (let i = 0; i < names.length; i += 1) {
    const name = names[i];

    if (vocabularies[name].defaultForSearch) {
      defaultSearchVocabulary = name;
      break;
    }
  }

  return defaultSearchVocabulary || names[0];
};

exports.getDefaultSearchVocabulary = getDefaultSearchVocabulary;

const findField = (parentFieldDescriptor, fieldName) => {
  const keys = Object.keys(parentFieldDescriptor);

  for (let i = 0; i < keys.length; i += 1) {
    const key = keys[i];
    const value = parentFieldDescriptor[key];

    if (key === fieldName) {
      return value;
    }

    if (key !== configKey) {
      const fieldDescriptor = findField(value, fieldName);

      if (fieldDescriptor) {
        return fieldDescriptor;
      }
    }
  }

  return null;
};

exports.findField = findField;

const findFieldConfigInPart = (recordTypeConfig, partName, fieldName) => {
  const partDescriptor = (0, _get.default)(recordTypeConfig, ['fields', 'document', "".concat(_recordDataHelpers.NS_PREFIX, ":").concat(partName)]);

  if (!partDescriptor) {
    return null;
  } // 1. Look for the field as a direct child of the part.


  let fieldDescriptor = partDescriptor[fieldName]; // 2. Check for a memoized result.

  if (!fieldDescriptor) {
    fieldDescriptor = (0, _get.default)(recordTypeConfig, ['fieldsByPart', partName, fieldName]);
  } // 3. Search for a nested field.


  if (typeof fieldDescriptor === 'undefined') {
    fieldDescriptor = findField(partDescriptor, fieldName); // Memoize the result.

    (0, _set.default)(recordTypeConfig, ['fieldsByPart', partName, fieldName], fieldDescriptor);
  }

  return fieldDescriptor ? fieldDescriptor[configKey] : null;
};

exports.findFieldConfigInPart = findFieldConfigInPart;

const findFieldsWithSource = (fieldDescriptor, shortId) => {
  const fieldsWithSource = (0, _flatMap.default)(Object.keys(fieldDescriptor).filter(key => key !== configKey), childFieldName => findFieldsWithSource(fieldDescriptor[childFieldName], shortId));
  const fieldConfig = fieldDescriptor[configKey];
  const source = (0, _get.default)(fieldConfig, ['view', 'props', 'source']);

  if (source === shortId) {
    fieldsWithSource.push(fieldConfig);
  }

  return fieldsWithSource;
};

const findVocabularyUses = (config, shortId) => {
  if (!shortId) {
    return null;
  }

  const uses = {};
  Object.values(config.recordTypes).forEach(recordTypeConfig => {
    const fieldDescriptor = recordTypeConfig.fields;

    if (fieldDescriptor) {
      const fields = findFieldsWithSource(recordTypeConfig.fields, shortId);

      if (fields.length > 0) {
        uses[recordTypeConfig.name] = fields;
      }
    }
  });
  return uses;
};

exports.findVocabularyUses = findVocabularyUses;

const getFirstColumnName = function getFirstColumnName(config, recordType) {
  let columnSetName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'default';
  const columnConfig = (0, _get.default)(config, ['recordTypes', recordType, 'columns', columnSetName]);

  if (!columnConfig) {
    return undefined;
  }

  const orderedColumnNames = Object.keys(columnConfig).filter(name => !columnConfig[name].disabled && columnConfig[name].formatValue !== _formatHelpers.formatWorkflowStateIcon && columnConfig[name].formatValue !== _blobHelpers.thumbnailImage).sort((nameA, nameB) => {
    const orderA = columnConfig[nameA].order;
    const orderB = columnConfig[nameB].order;
    return orderA - orderB;
  });
  return orderedColumnNames[0];
};

exports.getFirstColumnName = getFirstColumnName;

const getRecordFieldOptionListName = (recordType, rootPath) => {
  const atPath = rootPath ? "@".concat(rootPath) : '';
  return "_field_".concat(recordType).concat(atPath);
};

exports.getRecordFieldOptionListName = getRecordFieldOptionListName;

const getRecordGroupOptionListName = (recordType, rootPath) => {
  const atPath = rootPath ? "@".concat(rootPath) : '';
  return "_fieldgroup_".concat(recordType).concat(atPath);
};

exports.getRecordGroupOptionListName = getRecordGroupOptionListName;