Home Reference Source

src/kindergarten/rule/Definition.js

import {
  find,
  isArray,
  isEmpty,
  isFunction,
  isRegExp,
  memoize
} from 'lodash';

import BaseObject from '../BaseObject';
import {
  WrongRuleDefinition
} from '../errors';

export default class Definition extends BaseObject {
  constructor(rule, def) {
    super();

    this.TYPES = [
      [
        // The name of the definition type
        'items',
        // Condition that has to be met for raw value
        (ruleDef) => isArray(ruleDef) && !isEmpty(ruleDef),
        false // is not strict
      ],

      [
        // The name of the definition type
        'regex',
        // Condition that has to be met for raw value
        (ruleDef) => isRegExp(ruleDef),
        true // is strict
      ],

      [
        // The name of the definition type
        'customMethod',
        // Condition that has to be met for raw value
        (ruleDef) => isFunction(ruleDef),
        true // is strict
      ]
    ];

    this.rule = rule;

    this.raw = def;

    this._resolve();
  }

  isStrict() {
    return !this.rule.type.isPositive() ||
      this._isStrict(this.type);
  }

  _resolve() {
    const definitionObj = find(this.TYPES, (type) => {
      const condition = type[1];

      return condition(this.raw);
    }) || null;

    if (!isArray(definitionObj)) {
      throw new WrongRuleDefinition(
        `Cannot create a new rule "${this.rule.type.type}". Wrong rule definition.`
      );
    }

    if (isFunction(this.raw) && this.raw.ruleContext) {
      this.ruleContext = this.raw.ruleContext;
    }

    // set the type of the rule definition (items/customMethod/regex/...)
    [this.type] = definitionObj;

    this[this.type] = this.raw;
  }
}

Definition.prototype._isStrict = memoize(function (type) {
  return (find(this.TYPES, (t) => type === t[0]) || [])[2] || false;
});