Enum.js

import {UnsupportedError} from './errors';
import Serializable from './Serializable';
import {getType} from './utils';
/**
 *
 * @extends Serializable
 */
class Enum extends Serializable {
  /**
   *  An Enum constructor can take many different types to construct an Enum from:
   *
   * * String
   * * Comma-Delimited String
   * * Object
   * * Array
   * * Array of Objects
   * * Array of Strings
   * * Array of Arrays of Object
   * * etc.
   *
   * Once created an Enum is immutable.
   *
   * Enums inherit from the Serializable class so it also has:
   *
   * * `toObject()`
   * * `toJSON()`
   *
   * @example
   * const states = new Enum([
   *   'OPEN',
   *   'IN_PROGRESS',
   *   'CLOSED'
   * ]);
   *
   * console.info(states.OPEN) // 'OPEN'
   *
   * states.DONE = 'DONE'
   * console.info(states.DONE) // undefined
   *
   * const other_states = new Enum({
   *   'START': 'START',
   *   'IN_PROGRESS': 'IN_PROGRESS',
   *   'DONE': 'DONE'
   * })
   *
   * console.info(other_states.START) // 'START'
   *
   * other_states.DONE = 'DONE';
   * console.info(other_states.DONE) // undefined
   *
   * @summary
   * An Enum helper class that allows the user of many various setting methods
   *
   * @param {Object|Array<Object|String>|String} values
   * @throws {UnsupportedError}
   */
  constructor(values) {
    super();
    set.call(this, values);
    Object.freeze(this);
  }
}
/**
 *
 * @private
 * @param values
 */
function set(values) {
  switch (getType(values)) {
    case 'function':
      throw new UnsupportedError(values.name);
    case 'promise':
      throw new UnsupportedError(typeof values);
    case 'array':
      setFromArray.call(this, values);
      break;
    case 'object':
      setFromObject.call(this, values);
      break;
    case 'string':
      if (values.indexOf(',') > -1) {
        setFromArray.call(this, values.split(','));
      } else {
        setFromString.call(this, values);
      }
      break;
    default:
      throw new UnsupportedError(typeof values);
  }
}
/**
 *
 * @private
 * @param {Array} values
 */
function setFromArray(values) {
  for (let value of values) {
    set.call(this, value);
  }
}
/**
 *
 * @private
 * @param {Object} values
 */
function setFromObject(values) {
  for (let key of Object.keys(values)) {
    Object.assign(this, {
      [key]: values[key]
    });
  }
}
/**
 *
 * @private
 * @param {String} value
 */
function setFromString(value) {
  value = value.trim();
  Object.assign(this, {
    [value]: value
  });
}
export default Enum;