Source: lib/custom.js

var f = require('util').format,
  Mark = require("markup-js"),
  M = require('mstring'),
  utils = require('./utils'),
  generatePathAndObject = utils.generatePathAndObject;

/**
 * The CustomNode class represents a value that can be anything
 * 
 * @class
 * @return {CustomNode} a CustomNode instance.
 */
var CustomNode = function(parent, field, options) {  
  options = options || {};
  // Unique id for this node's generated method
  this.id = utils.generateId();
  // Link to parent node
  this.parent = parent;
  // The field related to this node
  this.field = field;
  // Any options
  this.options = options;
  // Just some metadata
  this.type = 'custom';
  // Custom context
  this.context = {};  
}

/**
 * Set the custom context for the custom validator (might include pre-compiled regular expressions)
 *
 * @method
 * @param {object} context the context for this custom validator node
 */
CustomNode.prototype.setContext = function(context) {
  this.context = context;
  return this;
}

/**
 * Set the custom validator function
 *
 * @method
 * @param {function} func the custom function validator
 */
CustomNode.prototype.setValidator = function(func) {
  this.validator = func;
  return this;
}

/**
 * Return the current object path
 *
 * @method
 * @return {array} an array containing the path to this node
 */
CustomNode.prototype.path = function() {
  if(this.parent == null) return [];
  return this.parent.path().concat([this.field]);
}

/**
 * Generate the code for this node
 *
 * @method
 * @param {object} context the generation context for this node
 */
CustomNode.prototype.generate = function(context) {
  // Set self
  var self = this;
  // Get the path
  var path = this.path().join('.');
  // Push ourselves to the rules array
  context.rules[this.id] = this;
  
  // Add this node context to the custom context object
  context.custom[this.id] = this.context;

  // Validation template
  var functionCallTemplate = M(function(){/***
    var error = custom_{{index}}(object, custom['{{index}}']);

    if(error instanceof Error && context.failOnFirst) {
      throw new ValidationError(error.message, path, rules[{{ruleIndex}}], object);       
    } else if(error instanceof Error) {
      errors.push(new ValidationError(error.message, path, rules[{{ruleIndex}}], object));
    }
  ***/});

  // Function template
  var functionTemplate = M(function(){/***
     var custom_{{index}} = {{function}};
  ***/});

  // Generate path and objectPath
  var paths = generatePathAndObject(self, context);

  // Unpack the custom validation
  var func = this.validator.toString();

  // Transform function
  var transformFunction = Mark.up(functionTemplate, {
    index: this.id, function: func
  });

  // Add the function to the complete list of functions
  context.functions.push(transformFunction);

  // Generate function call
  context.functionCalls.push(Mark.up(functionCallTemplate, {
      index: this.id,
      path: paths.path,
      ruleIndex: this.id,
      object: paths.objectPath
    }));
}

module.exports = CustomNode;
comments powered by Disqus