Browse files

Release 0.4.3

  • Loading branch information...
1 parent 54b712d commit cfc55c2f069e4e58f309780d061b2c3d5bd8974f @Baggz committed Dec 26, 2012
Showing with 3,720 additions and 1,610 deletions.
  1. +6 −18 docs/README.md
  2. +1 −1 package.json
  3. +2,016 −0 releases/0.4.3/amanda.js
  4. +26 −0 releases/0.4.3/amanda.min.js
  5. +1,646 −1,566 releases/latest/amanda.js
  6. +25 −25 releases/latest/amanda.min.js
View
24 docs/README.md
@@ -1,4 +1,3 @@
-<a name="documentation"></a>
# Documentation
### Engines
@@ -8,25 +7,14 @@
<a name="jsonSchema"></a>
## JSON Schema
-diff.md
-
-### Example
-
-```
-// Initialize a JSON Schema validator
-var jsonSchemaValidator = amanda('json');
-```
-
-<a name="methods"></a>
### Methods
-* [validate](https://github.com/Baggz/Amanda/tree/master/docs/json/methods/validate.md#validate)
-* [addAttribute](https://github.com/Baggz/Amanda/tree/master/docs/json/methods/validate.md#addAttribute)
-* [addAttributeConstructor](https://github.com/Baggz/Amanda/tree/master/docs/json/methods/validate.md#addAttributeConstructor)
+* [validate](./json/methods/validate.md)
+* [addAttribute](./json/methods/addAttribute.md)
+* [addAttributeConstructor](./json/methods/addAttributeConstructor.md)
-<a name="objects"></a>
### Objects
-* [Schema](https://github.com/Baggz/Amanda/tree/master/docs/json/objects/schema.md)
-* [Error](https://github.com/Baggz/Amanda/tree/master/docs/json/objects/error.md)
-* [Options](https://github.com/Baggz/Amanda/tree/master/docs/json/objects/options.md)
+* [Schema](./json/objects/schema.md)
+* [Error](./json/objects/error.md)
+* [Options](./json/objects/options.md)
View
2 package.json
@@ -2,7 +2,7 @@
"name": "amanda",
"description": "JSON Schema validator",
- "version": "0.4.2",
+ "version": "0.4.3",
"author": "František Hába <hello@frantisekhaba.com>",
"devDependencies": {
View
2,016 releases/0.4.3/amanda.js
@@ -0,0 +1,2016 @@
+(function() {
+
+ /**
+ * Engines
+ * --------------------
+ */
+ var engines = {};
+
+/**
+ * DetectType
+ *
+ * @param {object} input
+ */
+var detectType = function(input) {
+ return typeof input;
+};
+
+/**
+ * Each
+ *
+ * Applies an iterator function to each item in an array or an object, in series.
+ *
+ * @param {object} list
+ * @param {function} iterator
+ * @param {function} callback
+ */
+var each = function(list, iterator, callback) {
+
+ /**
+ * SyncEach
+ *
+ * @param {object} list
+ * @param {function} iterator
+ */
+ var syncEach = function(list, iterator) {
+
+ // If the list is an array
+ if (isArray(list) && !isEmpty(list)) {
+ for (var i = 0, len = list.length; i < len; i++) {
+ iterator.apply(list, [i, list[i]]);
+ }
+ }
+
+ // If the list is an object
+ if (isObject(list) && !isEmpty(list)) {
+ for (var key in list) {
+ if (list.hasOwnProperty(key)) {
+ iterator.apply(list, [key, list[key]]);
+ }
+ }
+ }
+
+ };
+
+ /**
+ * AsyncEach
+ * @param {object} list
+ * @param {function} iterator
+ * @param {function} callback
+ */
+ var asyncEach = function(list, iterator, callback) {
+
+ var queue = [];
+
+ /**
+ * AddToQueue
+ *
+ * @param {string} key
+ * @param {string|object} value
+ */
+ var addToQueue = function(key, value) {
+ var index = queue.length + 1;
+ queue.push(function() {
+
+ var next = function(error) {
+ var fn = queue[index];
+ if (!error && fn) {
+ return fn();
+ } else if (!error && !fn) {
+ return callback();
+ } else {
+ return callback(error);
+ }
+ };
+
+ return iterator(key, value, next);
+
+ });
+ };
+
+ // If the list is an array
+ if (isArray(list) && !isEmpty(list)) {
+ for (var i = 0, len = list.length; i < len; i++) {
+ addToQueue(i, list[i]);
+ }
+
+ // If the list is an object
+ } else if (isObject(list) && !isEmpty(list)) {
+ for (var key in list) {
+ if (list.hasOwnProperty(key)) {
+ addToQueue(key, list[key]);
+ }
+ }
+
+ // If the list is not an array or an object
+ } else {
+ return callback();
+ }
+
+ // And go!
+ return queue[0]();
+
+ };
+
+ if (typeof callback === 'undefined') {
+ return syncEach.apply(this, arguments);
+ } else {
+ return asyncEach.apply(this, arguments);
+ }
+
+};
+
+/**
+ * Every
+ *
+ * @param {object} arr
+ * @param {function} iterator
+ */
+var every = function(arr, iterator) {
+ return Array.prototype.every.apply(arr, [iterator]);
+};
+
+/**
+ * Filter
+ *
+ * @param {object} arr
+ * @param {function} iterator
+ */
+var filter = function(arr, iterator, context) {
+ return Array.prototype.filter.apply(arr, [iterator, context || this]);
+};
+
+/**
+ * HasProperty
+ *
+ * @param {object} input
+ */
+var hasProperty = function(obj, property) {
+ return Object.prototype.hasOwnProperty.apply(obj, [property]);
+};
+
+/**
+ * IsArray
+ *
+ * Returns true if the passed-in object is an array.
+ *
+ * @param {object} input
+ */
+var isArray = function(input) {
+ return Object.prototype.toString.call(input) === '[object Array]';
+};
+
+/**
+ * IsBoolean
+ *
+ * @param {object} input
+ */
+var isBoolean = function(input) {
+ return typeof input === 'boolean';
+};
+
+/**
+ * IsDefined
+ *
+ * @param {object} input
+ */
+var isDefined = function(input) {
+ return typeof input !== 'undefined';
+};
+
+/**
+ * IsEmpty
+ *
+ * Returns true if the passed-in object is empty.
+ *
+ * @param {object} input
+ */
+var isEmpty = function(input) {
+
+ if (isNumber(input)) {
+ return false;
+ }
+
+ if (input === null) {
+ return true;
+ }
+
+ // If the passed-in object is an array or a string
+ if (isArray(input) || typeof input === 'string') {
+ return input.length === 0;
+ }
+
+ // If the passed-in object is an object
+ if (isObject(input)) {
+ for (var key in input) {
+ if (hasOwnProperty.call(input, key)) return false;
+ }
+ }
+
+ return true;
+
+};
+
+/**
+ * IsEqual
+ *
+ * @param {object} obj1
+ * @param {object} obj2
+ */
+var isEqual = function(obj1, obj2) {
+
+ /**
+ * Arrays
+ */
+ if (isArray(obj1, obj2)) {
+
+ if (obj1.length !== obj2.length) {
+ return false;
+ }
+
+ return every(obj1, function(value, index, context) {
+ return obj2[index] === value;
+ });
+
+ }
+
+ /**
+ * Objects
+ */
+ if (isObject(obj1, obj2)) {
+
+ var keys1 = keys(obj1),
+ keys2 = keys(obj2);
+
+ if (!isEqual(keys1, keys2)) {
+ return false;
+ }
+
+ for (key in obj1) {
+ if (!obj2[key] || obj1[key] !== obj2[key]) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ return false;
+
+};
+
+/**
+ * IsFunction
+ *
+ * @param {object} input
+ */
+var isFunction = function(input) {
+ return typeof input === 'function';
+};
+
+/**
+ * IsInteger
+ *
+ * @param {object} input
+ */
+var isInteger = function(input) {
+ return isNumber(input) && input % 1 === 0;
+};
+
+/**
+ * IsNull
+ *
+ * @param {object} input
+ */
+var isNull = function(input) {
+ return input === null;
+};
+
+/**
+ * IsNumber
+ *
+ * @param {object} input
+ */
+var isNumber = function(input) {
+ return typeof input === 'number';
+};
+
+/**
+ * IsObject
+ *
+ * Returns true if the passed-in object is an object.
+ *
+ * @param {object} input
+ */
+var isObject = function(input) {
+ return Object.prototype.toString.call(input) === '[object Object]';
+};
+
+/**
+ * IsString
+ *
+ * @param {object} input
+ */
+var isString = function(input) {
+ return typeof input === 'string';
+};
+
+/**
+ * IsUndefined
+ *
+ * @param {object} input
+ */
+var isUndefined = function(input) {
+ return typeof input === 'undefined';
+};
+
+/**
+ * Keys
+ *
+ * @param {object} obj
+ */
+var keys = function(obj) {
+ return Object.keys(obj);
+};
+
+/**
+ * Merge
+ *
+ * Copy all of the properties in the source objects over to the destination object.
+ *
+ * @param {object} obj1
+ * @param {object} obj2
+ */
+var merge = function(obj1, obj2) {
+ for (var key in obj2) {
+ if (obj2.hasOwnProperty(key) && !obj1.hasOwnProperty(key)) {
+ obj1[key] = obj2[key];
+ }
+ }
+ return obj1;
+};
+
+/**
+ * Pluck
+ *
+ * Extracts a list of property values.
+ *
+ * @param {object} list
+ * @param {string} propertyName
+ */
+var pluck = function(list, propertyName) {
+ var output = [];
+ for (var i = 0, len = list.length; i < len; i++) {
+ var property = list[i][propertyName];
+ if (output.indexOf(property) === -1) {
+ output.push(property);
+ }
+ }
+ return output;
+};
+
+/**
+ * ReturnTrue
+ */
+var returnTrue = function() {
+ return true;
+};
+
+/**
+ * Some
+ *
+ * @param {object} arr
+ * @param {function} iterator
+ */
+var some = function(arr, iterator) {
+ return Array.prototype.some.apply(arr, [iterator]);
+};
+
+(function() {
+
+/**
+ * Validation
+ *
+ * @constructor
+ * @param {object} options
+ */
+var Validation = function(options) {
+
+ // Save a reference to the ‘this’
+ var self = this;
+
+ var defaultOptions = {
+ singleError: true,
+ messages: errorMessages,
+ cache: false
+ };
+
+ each(defaultOptions, function(key, value) {
+
+ if (isObject(value) && options[key]) {
+ self[key] = merge(options[key], defaultOptions[key]);
+
+ } else if (isObject(value) && !options[key]) {
+ self[key] = merge ({}, defaultOptions[key]);
+
+ } else {
+ self[key] = (isDefined(options[key])) ? options[key] : defaultOptions[key];
+ }
+
+ });
+
+ this.errors = new ValidationError(this);
+
+};
+
+/**
+ * Attributes
+ * --------------------
+ */
+Validation.prototype.attributes = {};
+
+/**
+ * AddAttribute
+ *
+ * @param {string} attributeName
+ * @param {function} attributeFn
+ */
+Validation.prototype.addAttribute = function(attributeName, attributeFn) {
+ return Validation.prototype.attributes[attributeName] = attributeFn;
+};
+
+/**
+ * AddAttributeConstructor
+ *
+ * @param {string} attributeName
+ * @param {function} attributeConstructor
+ */
+Validation.prototype.addAttributeConstructor = function(attributeName, attributeConstructor) {
+ return Validation.prototype.attributes[attributeName] = attributeConstructor();
+};
+
+/**
+ * AdditionalProperties
+ */
+var additionalPropertiesAttribute = function additionalProperties(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ var self = this;
+
+ /**
+ * {
+ * additionalProperties: true,
+ * ...
+ * }
+ */
+ if (attributeValue === true) {
+ return callback();
+ }
+
+ // Filter the forbidden properties
+ var propertyKeys = keys(propertyValue);
+ var forbiddenProperties = filter(propertyKeys, function(key) {
+ return !propertyAttributes.properties[key];
+ });
+
+ if (isEmpty(forbiddenProperties)) {
+ return callback();
+ }
+
+ /**
+ * {
+ * additionalProperties: false,
+ * ...
+ * }
+ */
+ if (attributeValue === false) {
+
+ forbiddenProperties.forEach(function(forbiddenProperty) {
+ this.addError({
+ property: this.joinPath(property, forbiddenProperty),
+ propertyValue: propertyValue[forbiddenProperty]
+ });
+ }, this);
+
+ return callback();
+
+ }
+
+ /**
+ * {
+ * additionalProperties: {
+ * type: 'string',
+ * ...
+ * },
+ * ...
+ * }
+ */
+ if (isObject(attributeValue)) {
+ return each(forbiddenProperties, function(index, key, callback) {
+ return self.validateSchema(
+ propertyValue[key],
+ attributeValue,
+ property + key,
+ callback
+ );
+ }, callback);
+ }
+
+};
+
+// Export
+Validation.prototype.addAttribute('additionalProperties', additionalPropertiesAttribute);
+
+/**
+ * DivisibleBy
+ */
+var divisibleByAttribute = function divisibleBy(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (attributeValue === 0) {
+ throw new Error('The value of this attribute should not be 0.');
+ }
+
+ if (isNumber(propertyValue) && (propertyValue % attributeValue !== 0)) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('divisibleBy', divisibleByAttribute);
+
+/**
+ * Enum
+ */
+var enumAttribute = function(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (attributeValue.indexOf(propertyValue) === -1) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('enum', enumAttribute);
+
+/**
+ * Except
+ */
+var exceptAttribute = function except(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (attributeValue.indexOf(propertyValue) !== -1) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('except', exceptAttribute);
+
+/**
+ * Format
+ */
+Validation.prototype.addAttributeConstructor('format', function formatConstructor() {
+
+ // Uložíme si referenci na this
+ var self = this;
+
+ /**
+ * Formats
+ */
+ var formats = {
+
+ /**
+ * date-time
+ *
+ * This should be a date in ISO 8601 format of YYYY-MM-DDThh:mm:ssZ in UTC
+ * time. This is the recommended form of date/timestamp.
+ */
+ 'date-time': {
+ type: 'string',
+ pattern: /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
+ },
+
+ /**
+ * date
+ *
+ * This should be a date in the format of YYYY-MM-DD. It is recommended that you
+ * use the "date-time" format instead of "date" unless you need to transfer only the date part.
+ */
+ date: function(input) {
+ if (isString(input)) {
+ return input.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/);
+ }
+ if (isObject(input)) {
+ return Object.prototype.toString.call(input) === '[object Date]';
+ }
+ return false;
+ },
+
+ /**
+ * time
+ *
+ * This should be a time in the format of hh:mm:ss.
+ */
+ 'time': {
+ type: 'string',
+ pattern: /^\d{2}:\d{2}:\d{2}$/
+ },
+
+ /**
+ * utc-milisec
+ *
+ * This should be the difference, measured in milliseconds, between the specified
+ * time and midnight, 00:00 of January 1, 1970 UTC. The value
+ * should be a number (integer or float).
+ */
+ 'utc-milisec': {
+ type: 'number'
+ },
+
+ /**
+ * regex
+ *
+ * This should be a time in the format of hh:mm:ss.
+ */
+ regex: function(input) {
+ return input && input.test && input.exec;
+ },
+
+ /**
+ * color
+ *
+ * This is a CSS color (like "#FF0000" or "red"), based on CSS 2.1.
+ */
+ 'color': {
+ type: 'string'
+ },
+
+ /**
+ * style
+ *
+ * This is a CSS style definition (like "color: red; background-color:#FFF"), based on CSS 2.1.
+ */
+ 'style': {
+ type: 'string'
+ },
+
+ /**
+ * phone
+ *
+ * This should be a phone number.
+ */
+ 'phone': {
+ type: 'number'
+ },
+
+ /**
+ * uri
+ *
+ * This value should be a URI.
+ */
+ 'uri': {
+ type: 'string',
+ pattern: /^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/
+ },
+
+ /**
+ * email
+ *
+ * This should be an email address.
+ */
+ 'email': {
+ type: 'string',
+ pattern: /^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/
+ },
+
+ /**
+ * ip-address
+ *
+ * This should be an ip version 4 address.
+ */
+ 'ip-address': {
+ type: 'string',
+ pattern: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
+ },
+
+ /**
+ * ipv6
+ *
+ * This should be an ip version 6 address.
+ */
+ 'ipv6': {
+ type: 'string',
+ pattern: /(?:(?:[a-f\d]{1,4}:)*(?:[a-f\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-f\d]{1,4}:)*[a-f\d]{1,4})?::(?:(?:[a-f\d]{1,4}:)*(?:[a-f\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)/
+ },
+
+ /**
+ * host-name
+ *
+ * This should be a host-name.
+ */
+ 'host-name': {
+ type: 'string'
+ }
+
+ };
+
+ /**
+ * CustomFormats
+ * --------------------
+ */
+ formats.alpha = {
+ required: true,
+ type: 'string',
+ pattern: /^[a-zA-Z]+$/
+ };
+
+ formats.alphanumeric = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /^[a-zA-Z0-9]+$/
+ };
+
+ formats.decimal = function(input) {
+ if (!isNumber(input)) return false;
+ return (input + '').match(/^[0-9]+(\.[0-9]{1,2})?$/);
+ };
+
+ formats.percentage = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,
+ minimum: -100,
+ maximum: 100
+ };
+
+ formats.port = {
+ required: true,
+ type: ['string', 'number'],
+ pattern: /\:\d+/
+ };
+
+ /**
+ * Aliases
+ * --------------------
+ */
+ var aliases = {
+ url: 'uri',
+ ip: 'ip-address',
+ ipv4: 'ip-address',
+ host: 'host-name',
+ hostName: 'host-name'
+ };
+
+ // Apply aliases
+ each(aliases, function(alias, format) {
+ formats[alias] = formats[format];
+ });
+
+ // Export
+ return function format(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ /**
+ * {
+ * format: {
+ * type: 'string',
+ * pattern: /abc/
+ * ...
+ * }
+ * ...
+ * }
+ */
+ if (isObject(attributeValue)) {
+ return this.validateProperty(property, propertyValue, attributeValue, callback);
+ }
+
+ /**
+ * {
+ * format: 'lorem ipsum dolor',
+ * ...
+ * }
+ */
+ if (isString(attributeValue) && !hasProperty(formats, attributeValue)) {
+ throw new Error('The format ‘' + attributeValue + '’ is not supported.');
+ }
+
+ /**
+ * {
+ * format: 'phone',
+ * ...
+ * }
+ */
+ if (isString(attributeValue)) {
+
+ var fn = formats[attributeValue];
+
+ if (isFunction(fn)) {
+ var noError = fn(propertyValue);
+ if (!noError) {
+ this.addError();
+ }
+ return callback();
+ }
+
+ if (isObject(fn)) {
+ return this.validateProperty(property, propertyValue, fn, callback);
+ }
+
+ }
+
+ };
+
+});
+
+/**
+ * Length
+ */
+var lengthAttribute = function length(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isString(propertyValue) && propertyValue.length !== attributeValue) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('length', lengthAttribute);
+
+/**
+ * Maximum
+ */
+var maximumAttribute = function maximum(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isNumber(propertyValue)) {
+ if ((propertyAttributes.exclusiveMaximum && propertyValue >= attributeValue) || (propertyValue > attributeValue)) {
+ this.addError();
+ }
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('maximum', maximumAttribute);
+
+/**
+ * MaxItems
+ */
+var maxItemsAttribute = function maxItems(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isArray(propertyValue) && propertyValue.length > attributeValue) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('maxItems', maxItemsAttribute);
+
+/**
+ * MaxLength
+ */
+var maxLengthAttribute = function maxLength(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isString(propertyValue) && propertyValue.length > attributeValue) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('maxLength', maxLengthAttribute);
+
+/**
+ * Minimum
+ */
+var minimumAttribute = function minimum(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isNumber(propertyValue)) {
+ if ((propertyAttributes.exclusiveMinimum && propertyValue <= attributeValue) || (propertyValue < attributeValue)) {
+ this.addError();
+ }
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('minimum', minimumAttribute);
+
+
+/**
+ * MinItems
+ */
+var minItems = function minItems(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isArray(propertyValue) && propertyValue.length < attributeValue) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('minItems', minItems);
+
+/**
+ * MinLength
+ */
+var minLengthAttribute = function minLength(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isString(propertyValue) && propertyValue.length < attributeValue) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('minLength', minLengthAttribute);
+
+/**
+ * Pattern
+ */
+var patternAttribute = function pattern(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (isString(propertyValue) && !propertyValue.match(attributeValue)) {
+ this.addError();
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('pattern', patternAttribute);
+
+(function() {
+
+ /**
+ * PatternProperties
+ */
+ var attribute = function patternProperties(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ // Saves a reference to ‘this’
+ var self = this;
+
+ // Skip
+ if (isEmpty(attributeValue)) {
+ return callback();
+ }
+
+ var matches = {};
+ var patterns = keys(attributeValue);
+
+ each(propertyValue, function(key, value) {
+
+ each(patterns, function(index, pattern) {
+ if (key.match(new RegExp(pattern))) {
+ matches[key] = attributeValue[pattern];
+ }
+ });
+
+ });
+
+ if (isEmpty(matches)) {
+ return callback();
+ }
+
+ each(matches, function(propertyName, propertySchema, callback) {
+ return self.validateSchema(
+ propertyValue[propertyName],
+ propertySchema,
+ self.joinPath(property, propertyName),
+ callback
+ );
+ }, callback);
+
+ };
+
+ // Export
+ Validation.prototype.addAttribute('patternProperties', attribute);
+
+}());
+
+/**
+ * Required
+ */
+var requiredAttribute = function required(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ if (attributeValue) {
+
+ var undefinedCondition = isUndefined(propertyValue);
+ var emptyCondition = (isString(propertyValue) || isArray(propertyValue) || isObject(propertyValue)) && isEmpty(propertyValue);
+
+ if (undefinedCondition || emptyCondition) {
+ this.addError();
+ }
+
+ }
+
+ return callback();
+
+};
+
+// Export
+Validation.prototype.addAttribute('required', requiredAttribute);
+
+/**
+ * Type
+ */
+var typeConstructor = function typeConstructor() {
+
+ /**
+ * Types
+ */
+ var types = {
+ 'string': isString,
+ 'number': isNumber,
+ 'function': isFunction,
+ 'boolean': isBoolean,
+ 'object': isObject,
+ 'array': isArray,
+ 'integer': isInteger,
+ 'int': isInteger,
+ 'null': isNull,
+ 'any': returnTrue
+ };
+
+ // Export
+ return function type(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ /**
+ * {
+ * type: ['string', 'number']
+ * }
+ */
+ if (isArray(attributeValue)) {
+
+ var noError = attributeValue.some(function(type) {
+
+ if (!hasProperty(types, type)) {
+ throw new Error('Type ‘' + attributeValue + '’ is not supported.');
+ }
+
+ return types[type](propertyValue);
+
+ });
+
+ if (!noError) {
+ this.errors.addError();
+ }
+
+ return callback();
+
+ /**
+ * {
+ * type: 'string'
+ * }
+ */
+ } else {
+
+ if (!hasProperty(types, attributeValue)) {
+ throw new Error('Type ‘' + attributeValue + '’ is not supported.');
+ }
+
+ if (!types[attributeValue](propertyValue)) {
+ this.addError();
+ }
+
+ return callback();
+
+ }
+
+ };
+
+};
+
+// Export
+Validation.prototype.addAttributeConstructor('type', typeConstructor);
+
+(function() {
+
+ /**
+ * UniqueItems
+ */
+ var attribute = function uniqueItems(property, propertyValue, attributeValue, propertyAttributes, callback) {
+
+ var self = this;
+
+ each(propertyValue, function(index, value) {
+
+ if (isString(value)) {
+ if ((propertyValue.indexOf(value) < index)) {
+ self.addError();
+ }
+ }
+
+ if (isObject(value) || isArray(value)) {
+ propertyValue.forEach(function(subValue, subIndex) {
+
+ if (subIndex !== index) {
+ if (isEqual(value, subValue)) {
+ self.addError({
+ property: self.joinPath(property, subIndex)
+ });
+ }
+ }
+
+ });
+ }
+
+ });
+
+ return callback();
+
+ };
+
+ // Export
+ Validation.prototype.addAttribute('uniqueItems', attribute);
+
+}());
+
+/**
+ * Error
+ *
+ * @constructor
+ */
+var ValidationError = function(parent) {
+
+ this.length = 0;
+
+ this.errorMessages = parent.messages;
+
+};
+
+ValidationError.prototype.renderErrorMessage = function(error) {
+
+ var errorMessage = this.errorMessages[error.attributeName];
+
+ if (errorMessage && isFunction(errorMessage)) {
+ return errorMessage(
+ error.property,
+ error.propertyValue,
+ error.attributeValue
+ );
+ }
+
+ if (errorMessage && isString(errorMessage)) {
+
+ [
+ 'property',
+ 'propertyValue',
+ 'attributeValue'
+ ].forEach(function(placeholder) {
+ errorMessage = errorMessage.replace(new RegExp('{{' + placeholder + '}}', 'g'), error[placeholder]);
+ });
+
+ // Deprecated
+ errorMessage = errorMessage.replace(/{{validator}}/g, error['attributeValue']);
+
+ return errorMessage.replace(/\s+/g, ' ');
+
+ }
+
+ return error.message;
+
+};
+
+ValidationError.prototype.push = function(error) {
+
+ this[this.length] = {
+
+ property: error.property,
+ propertyValue: error.propertyValue,
+ attributeName: error.attributeName,
+ attributeValue: error.attributeValue,
+ message: this.renderErrorMessage(error),
+
+ // Deprecated
+ validator: error.attributeName,
+ validatorName: error.attributeName,
+ validatorValue: error.attributeValue
+
+ };
+
+ this.length += 1;
+
+};
+
+/**
+ * GetProperties
+ */
+ValidationError.prototype.getProperties = function() {
+ return pluck(this, 'property');
+};
+
+/**
+ * GetMessages
+ */
+ValidationError.prototype.getMessages = function() {
+ return pluck(this, 'message');
+};
+
+/**
+ * Messages
+ * --------------------
+ */
+var vowels = "aeiou",
+errorMessages = {
+
+ /**
+ * Maximum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ required: function(property, propertyValue, attributeValue) {
+ return 'The ‘' + property + '’ property is required.';
+ },
+
+ /**
+ * MinLength
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ minLength: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ' + property + ' property must be at least ' + attributeValue + ' characters.',
+ 'The length of the property is ' + propertyValue.length + '.'
+ ].join(' ');
+ },
+
+ /**
+ * MaxLength
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ maxLength: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ' + property + ' property must not exceed ' + attributeValue + ' character' + (attributeValue > 1 ? 's' : '') + '.',
+ 'The length of the property is ' + propertyValue.length + '.'
+ ].join(' ');
+ },
+
+ /**
+ * MaxLength
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ length: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ' + property + ' property must be exactly ' + attributeValue + ' character' + (attributeValue > 1 ? 's' : '') + '.',
+ 'The length of the property is ' + propertyValue.length + '.'
+ ].join(' ');
+ },
+
+ /**
+ * Format
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ format: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ‘' + property + '’ property must be a/an ‘' + attributeValue + '’.',
+ 'The current value of the property is ‘' + propertyValue + ''
+ ].join(' ');
+ },
+
+ /**
+ * Type
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ type: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ‘' + property + '’ property must be ' + (vowels.indexOf(attributeValue[0]) > -1 ? 'an' : 'a') + '' + attributeValue + '’.',
+ 'The type of the property is ‘' + detectType(propertyValue) + ''
+ ].join(' ');
+ },
+
+ /**
+ * Except
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ except: function(property, propertyValue, attributeValue) {
+ return;
+ },
+
+ /**
+ * Minimum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ minimum: function(property, propertyValue, attributeValue) {
+ return [
+ 'The minimum value of the ‘' + property + '’ must be ' + attributeValue + '.',
+ 'The current value of the property is ‘' + propertyValue + ''
+ ].join(' ');
+ },
+
+ /**
+ * Maximum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ maximum: function(property, propertyValue, attributeValue) {
+ return [
+ 'The maximum value of the ‘' + property + '’ must be ' + attributeValue + '.',
+ 'The current value of the property is ‘' + propertyValue + '’.'
+ ].join(' ');
+ },
+
+ /**
+ * Maximum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ pattern: function(property, propertyValue, attributeValue) {
+ return 'The ‘' + property + '’ does not match the ‘' + attributeValue + '’ pattern.';
+ },
+
+ /**
+ * MaxItems
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ maxItems: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ‘' + property + '’ property must not contain more than ‘' + attributeValue + '’ items.',
+ 'Currently it contains ‘' + propertyValue.items + '’ items.'
+ ].join(' ');
+ },
+
+ /**
+ * MinItems
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ minItems: function(property, propertyValue, attributeValue) {
+ return [
+ 'The ‘' + property + '’ property must contain at least ‘' + attributeValue + '’ items.',
+ 'Currently it contains ‘' + propertyValue.items + '’ items.'
+ ].join(' ');
+ },
+
+ /**
+ * Maximum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ divisibleBy: function(property, propertyValue, attributeValue) {
+ return 'The ‘' + property + '’ is not divisible by ‘' + attributeValue + '’.';
+ },
+
+ /**
+ * Maximum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ uniqueItems: function(property, propertyValue, attributeValue) {
+ return 'All items in the ‘' + property + '’ property must be unique.';
+ },
+
+ /**
+ * Enum
+ *
+ * @param {string} property
+ * @param {any} propertyValue
+ * @param {string} attributeValue
+ */
+ 'enum': function(property, propertyValue, attributeValue) {
+ return 'Value of the ‘' + property + '’ must be ' + attributeValue.join(' or ') + '.';
+ }
+
+};
+
+/**
+ * GetProperty
+ *
+ * @param {string} property
+ * @param {object} source
+ */
+Validation.prototype.getProperty = function(property, source) {
+ if (source) {
+ return (source[property]) ? source[property] : undefined;
+ } else {
+ return undefined;
+ }
+};
+
+/**
+ * JoinPath
+ *
+ * @param {string} path
+ * @param {string} property
+ */
+Validation.prototype.joinPath = function(path, property) {
+
+ // If the ‘path’ is undefined (object), convert the path to a string
+ path = path || '';
+
+ // Converts the ‘property’ to a string
+ property = property + '';
+
+ if (property.match(/^[a-zA-Z][a-zA-Z0-9]*$/)) {
+ return (path) ? (path + '.' + property) : property;
+ } else if (property.match(/\d+/)) {
+ return path + '[' + property + ']';
+ } else {
+ return path + '["' + property + '"]';
+ }
+
+};
+
+/**
+ * Validation.validate
+ *
+ * @param {object} instance
+ * @param {object} schema
+ * @param {boolean} singleError
+ * @param {function} callback
+ */
+Validation.prototype.validate = function(instance, schema, callback) {
+
+ // Save a reference to the ‘this’
+ var self = this;
+
+ this.instance = instance;
+ this.schema = schema;
+
+ /**
+ * Basic Types
+ */
+ var basicTypes = [
+ 'string',
+ 'number',
+ 'function',
+ 'boolean',
+ 'integer',
+ 'int',
+ 'null'
+ ];
+
+ /**
+ * Object Types
+ */
+ var objectTypes = [
+ 'object',
+ 'array'
+ ];
+
+ /**
+ * CallbackProxy
+ */
+ var callbackProxy = function() {
+ if (self.errors.length !== 0) {
+ return callback(self.errors);
+ } else {
+ return callback();
+ }
+ };
+
+ /**
+ * {
+ * type: 'string',
+ * ...
+ * }
+ */
+ if (basicTypes.indexOf(schema.type) !== -1) {
+ return this.validateProperty(undefined, instance, schema, callbackProxy);
+ }
+
+ /**
+ * {
+ * type: 'object',
+ * ...
+ * }
+ */
+ if (objectTypes.indexOf(schema.type) !== -1) {
+
+ if (isString(instance)) {
+ try {
+ instance = JSON.parse(instance);
+ } catch(parseError) {
+
+ }
+ }
+
+ return this.validateSchema(instance, schema, '', callbackProxy);
+
+ }
+
+ /**
+ * {
+ * type: ???,
+ * ...
+ * }
+ */
+ if (schema.type === 'any' || !schema.type) {
+
+ if (isString(instance)) {
+ try {
+ instance = JSON.parse(instance);
+ return this.validateSchema(instance, schema, '', callbackProxy);
+ } catch(parseError2) {
+
+ }
+ }
+
+ if (isObject(instance) || isArray (instance)) {
+ return this.validateSchema(instance, schema, '', callbackProxy);
+ }
+
+ return this.validateProperty(undefined, instance, schema, callbackProxy);
+
+ }
+
+};
+
+/**
+ * Validation.validateItems
+ *
+ * @param {object} instance
+ * @param {object} schema
+ * @param {string} path
+ * @param {function} callback
+ */
+Validation.prototype.validateItems = function(instance, schema, path, callback) {
+
+ // Save a reference to the ‘this’
+ var self = this;
+
+ /**
+ * {
+ * type: 'array'
+ * items: [
+ * {
+ * type: 'string'
+ * },
+ * {
+ * type: 'number'
+ * },
+ * ...
+ * ],
+ * ...
+ * }
+ */
+ if (isArray(schema.items)) {
+
+ // Additional items are allowed
+ if (isUndefined(schema.additionalItems) || schema.additionalItems === true) {
+ return each(schema.items, function(itemIndex, itemSchema, callback) {
+ return self.validateSchema(
+ instance[itemIndex],
+ itemSchema,
+ self.joinPath(path, itemIndex),
+ callback
+ );
+ }, callback);
+ }
+
+ return each(instance, function(itemIndex, itemValue, callback) {
+
+ // The ‘additionalItems’ attribute is a schema that defines
+ // the schema of the additional items
+ if (schema.items[itemIndex] || isObject(schema.additionalItems)) {
+ return self.validateSchema(
+ itemValue,
+ schema.items[itemIndex],
+ self.joinPath(path, itemIndex),
+ callback
+ );
+ }
+
+ // Additional items are disallowed
+ if (schema.additionalItems === false) {
+ self.errors.push({
+ property: self.joinPath(path, itemIndex),
+ propertyValue: itemValue,
+ attributeName: 'additionalItems',
+ attributeValue: false
+ });
+ return callback();
+ }
+
+ }, callback);
+
+ }
+
+ /**
+ * {
+ * type: 'array'
+ * items: {
+ * type: 'string'
+ * },
+ * ...
+ * }
+ */
+ if (isObject(schema.items) && instance && !isEmpty(instance)) {
+ return each(instance, function(itemIndex, itemValue, callback) {
+ return self.validateSchema(
+ instance[itemIndex],
+ schema.items,
+ self.joinPath(path, itemIndex),
+ callback
+ );
+ }, callback);
+ } else {
+ return callback();
+ }
+
+};
+
+/**
+ * Validation.validateProperties
+ *
+ * @param {object} instance
+ * @param {object} schema
+ * @param {string} path
+ * @param {function} callback
+ */
+Validation.prototype.validateProperties = function(instance, schema, path, callback) {
+
+ // Save a reference to the ‘this’
+ var self = this;
+
+ // Goes
+ return each(schema.properties, function(property, propertyAttributes, callback) {
+
+ var isObject = propertyAttributes.type === 'object' && propertyAttributes.properties,
+ isArray = propertyAttributes.type === 'array';
+
+ // Get the value of property (instance[property])
+ var propertyValue = self.getProperty(property, instance);
+ var propertyPath = self.joinPath(path, property);
+
+ /**
+ * {
+ * type: 'object',
+ * properties: {
+ * user: {
+ * type: 'object',
+ * properties: {
+ * ...
+ * }
+ * }
+ * }
+ * }
+ */
+ if (isObject || isArray) {
+ return self.validateSchema(
+ propertyValue,
+ schema.properties[property],
+ propertyPath,
+ callback
+ );
+ } else {
+ return self.validateProperty(
+ propertyPath,
+ propertyValue,
+ propertyAttributes,
+ callback
+ );
+ }
+
+ }, callback);
+
+};
+
+/**
+ * Validation.validateProperty
+ *
+ * @param {string} propertyName
+ * @param {object} propertyAttributes
+ * @param {string|object} propertyValue
+ * @param {boolean} singleError
+ * @param {function} callback
+ */
+Validation.prototype.validateProperty = function(property, propertyValue, propertyAttributes, callback) {
+
+ // Save a reference to the ‘this’
+ var self = this;
+
+ var context = {};
+
+ [
+ 'validateItems',
+ 'validateProperties',
+ 'validateSchema',
+ 'validateProperty',
+ 'getProperty',
+ 'attributes',
+ 'errors',
+ 'joinPath'
+ ].forEach(function(key) {
+ context[key] = this[key];
+ }, self);
+
+ /**
+ * Iterator
+ *
+ * @param {string} attributeName
+ * @param {function} attributeFn
+ * @param {function} callback
+ */
+ var iterator = function(attributeName, attributeFn, callback) {
+
+ var lastLength = self.errors.length;
+
+ // Overwrite the ‘addError’ method
+ context.addError = function(message) {
+
+ if (isObject(message)) {
+ return self.errors.push({
+ property: message.property || property,
+ propertyValue: message.propertyValue || propertyValue,
+ attributeName: message.attributeName || attributeName,
+ attributeValue: message.attributeValue || propertyAttributes[attributeName],
+ message: message.message || undefined
+ });
+ }
+
+ return self.errors.push({
+ property: property,
+ propertyValue: propertyValue,
+ attributeName: attributeName,
+ attributeValue: propertyAttributes[attributeName],
+ message: message
+ });
+
+ };
+
+ /**
+ * OnComplete
+ */
+ var onComplete = function(error) {
+
+ // Deprecated
+ if (error === true || isString(error)) {
+ context.addError(error);
+ return callback(true);
+ };
+
+ if (self.errors.length > lastLength && self.singleError) {
+ return callback(true);
+ } else {
+ return callback();
+ }
+
+ };
+
+ if (isDefined(propertyAttributes[attributeName])) {
+ return attributeFn.apply(context, [
+ property,
+ propertyValue,
+ propertyAttributes[attributeName],
+ propertyAttributes,
+ onComplete
+ ]);
+ } else {
+ return callback();
+ }
+
+ };
+
+ // If it's not a required param and it's empty, skip
+ if (propertyAttributes.required !== true && isUndefined(propertyValue)) {
+ return callback();
+ }
+
+ // Validate the property
+ return each(self.attributes, iterator, callback);
+
+};
+
+/**
+ * Validation.validateSchema
+ *
+ * @param {object} instance
+ * @param {object} schema
+ * @param {string} path
+ * @param {function} callback
+ */
+Validation.prototype.validateSchema = function(instance, schema, path, callback) {
+
+ var self = this;
+
+ return self.validateProperty(path, instance, schema, function(error) {
+
+ /**
+ * {
+ * type: 'object',
+ * properties: {
+ * ...
+ * }
+ * }
+ */
+ if (schema.properties) {
+ return self.validateProperties(
+ instance,
+ schema,
+ path,
+ callback
+ );
+
+ /**
+ * {
+ * type: 'array',
+ * items: {
+ * type: 'string'
+ * ...
+ * }
+ * }
+ */
+ } else if (schema.items) {
+ return self.validateItems(
+ instance,
+ schema,
+ path,
+ callback
+ );
+
+ /**
+ * {
+ * type: 'array'
+ * }
+ * — or —
+ * {
+ * type: 'object'
+ * }
+ */
+ } else {
+ return callback();
+ }
+
+ });
+
+};
+
+
+ /**
+ * Export
+ * --------------------
+ */
+ engines.json = (function() {
+
+ /**
+ * Cache
+ */
+ var cache = [];
+ var cacheIndex = {};
+
+ return {
+
+ /**
+ * Validate
+ *
+ * @param {object} instance
+ * @param {object} schema
+ * @param {object} options
+ * @param {function} callback
+ */
+ validate: function(instance, schema, options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ return (new Validation(options)).validate(instance, schema, callback);
+ },
+
+ /**
+ * AddAttribute
+ *
+ * @param {string} attributeName
+ * @param {function} attributeFn
+ */
+ addAttribute: function(attributeName, attributeFn) {
+ return Validation.prototype.addAttribute.apply(Validation, arguments);
+ },
+
+ /**
+ * AddAttributeConstructor
+ *
+ * @param {string} attributeName
+ * @param {function} attributeConstructor
+ */
+ addAttributeConstructor: function(attributeName, attributeConstructor) {
+ return Validation.prototype.addAttributeConstructor.apply(Validation, arguments);
+ }
+
+ };
+
+ }());
+
+}());
+
+var amanda = function(engine) {
+
+ if (!hasProperty(engines, engine)) {
+ throw new Error('The ‘' + engine + '’ engine is not supported. Please use a different one.');
+ }
+
+ return engines[engine];
+
+};
+
+/**
+ * Amanda.validate
+ *
+ * This method is deprecated, please use ‘amanda('json').validate’ instead.
+ */
+amanda.validate = function(instance, schema, options, callback) {
+ var json = engines.json;
+ return json.validate.apply(json, arguments);
+};
+
+/**
+ * Amanda.addValidator
+ *
+ * This method is deprecated, please use ‘amanda('json').addValidator’ instead.
+ */
+amanda.addValidator = function(attributeName, attributeFn) {
+ var json = engines.json;
+ return json.addAttribute.apply(json, arguments);
+};
+
+/**
+ * Amanda.addAttribute
+ *
+ * This method is deprecated, please use ‘amanda('json').addAttribute’ instead.
+ */
+amanda.addAttribute = function(attributeName, attributeFn) {
+ var json = engines.json;
+ return json.addAttribute.apply(json, arguments);
+};
+
+/**
+ * Amanda.addAttributeConstructor
+ *
+ * This method is deprecated, please use ‘amanda('json').addAttributeConstructor’ instead.
+ */
+amanda.addAttributeConstructor = function(attributeName, attributeConstructor) {
+ var json = engines.json;
+ return json.addAttributeConstructor.apply(json, arguments);
+};
+
+ /**
+ * Export
+ * --------------------
+ */
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = amanda;
+ } else if (typeof define !== 'undefined') {
+ define(function() {
+ return amanda;
+ });
+ } else {
+ this.amanda = amanda;
+ }
+
+}());
View
26 releases/0.4.3/amanda.min.js
@@ -0,0 +1,26 @@
+(function(){var n={},j=function(a,b,c){var d=function(a,b){if(h(a)&&!m(a))for(var c=0,e=a.length;c<e;c++)b.apply(a,[c,a[c]]);if(g(a)&&!m(a))for(var d in a)a.hasOwnProperty(d)&&b.apply(a,[d,a[d]])},e=function(a,b,c){var e=[],d=function(a,d){var f=e.length+1;e.push(function(){return b(a,d,function(a){var b=e[f];return!a&&b?b():!a&&!b?c():c(a)})})};if(h(a)&&!m(a))for(var f=0,s=a.length;f<s;f++)d(f,a[f]);else if(g(a)&&!m(a))for(f in a)a.hasOwnProperty(f)&&d(f,a[f]);else return c();return e[0]()};return"undefined"===
+typeof c?d.apply(this,arguments):e.apply(this,arguments)},A=function(a,b,c){return Array.prototype.filter.apply(a,[b,c||this])},h=function(a){return"[object Array]"===Object.prototype.toString.call(a)},B=function(a){return"boolean"===typeof a},m=function(a){if(p(a))return!1;if(null===a)return!0;if(h(a)||"string"===typeof a)return 0===a.length;if(g(a))for(var b in a)if(hasOwnProperty.call(a,b))return!1;return!0},v=function(a,b){if(h(a,b))return a.length!==b.length?!1:Array.prototype.every.apply(a,
+[function(a,c){return b[c]===a}]);if(g(a,b)){var c=Object.keys(a),d=Object.keys(b);if(!v(c,d))return!1;for(key in a)if(!b[key]||a[key]!==b[key])return!1;return!0}return!1},t=function(a){return"function"===typeof a},w=function(a){return p(a)&&0===a%1},C=function(a){return null===a},p=function(a){return"number"===typeof a},g=function(a){return"[object Object]"===Object.prototype.toString.call(a)},k=function(a){return"string"===typeof a},u=function(a){return"undefined"===typeof a},x=function(a,b){for(var c in b)b.hasOwnProperty(c)&&
+!a.hasOwnProperty(c)&&(a[c]=b[c]);return a},y=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++){var f=a[d][b];-1===c.indexOf(f)&&c.push(f)}return c},D=function(){return!0},f=function(a){var b=this,c={singleError:!0,messages:E,cache:!1};j(c,function(d,e){b[d]=g(e)&&a[d]?x(a[d],c[d]):g(e)&&!a[d]?x({},c[d]):"undefined"!==typeof a[d]?a[d]:c[d]});this.errors=new r(this)};f.prototype.attributes={};f.prototype.addAttribute=function(a,b){return f.prototype.attributes[a]=b};f.prototype.addAttributeConstructor=
+function(a,b){return f.prototype.attributes[a]=b()};f.prototype.addAttribute("additionalProperties",function(a,b,c,d,e){var f=this;if(!0===c)return e();var l=Object.keys(b),l=A(l,function(a){return!d.properties[a]});if(m(l))return e();if(!1===c)return l.forEach(function(c){this.addError({property:this.joinPath(a,c),propertyValue:b[c]})},this),e();if(g(c))return j(l,function(d,e,l){return f.validateSchema(b[e],c,a+e,l)},e)});f.prototype.addAttribute("divisibleBy",function(a,b,c,d,e){if(0===c)throw Error("The value of this attribute should not be 0.");
+p(b)&&0!==b%c&&this.addError();return e()});f.prototype.addAttribute("enum",function(a,b,c,d,e){-1===c.indexOf(b)&&this.addError();return e()});f.prototype.addAttribute("except",function(a,b,c,d,e){-1!==c.indexOf(b)&&this.addError();return e()});f.prototype.addAttributeConstructor("format",function(){var a={"date-time":{type:"string",pattern:/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/},date:function(a){return k(a)?a.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/):g(a)?"[object Date]"===
+Object.prototype.toString.call(a):!1},time:{type:"string",pattern:/^\d{2}:\d{2}:\d{2}$/},"utc-milisec":{type:"number"},regex:function(a){return a&&a.test&&a.exec},color:{type:"string"},style:{type:"string"},phone:{type:"number"},uri:{type:"string",pattern:/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/},
+email:{type:"string",pattern:/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/},"ip-address":{type:"string",pattern:/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/},ipv6:{type:"string",pattern:/(?:(?:[a-f\d]{1,4}:)*(?:[a-f\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})|(?:(?:[a-f\d]{1,4}:)*[a-f\d]{1,4})?::(?:(?:[a-f\d]{1,4}:)*(?:[a-f\d]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))?)/},
+"host-name":{type:"string"},alpha:{required:!0,type:"string",pattern:/^[a-zA-Z]+$/},alphanumeric:{required:!0,type:["string","number"],pattern:/^[a-zA-Z0-9]+$/},decimal:function(a){return!p(a)?!1:(a+"").match(/^[0-9]+(\.[0-9]{1,2})?$/)},percentage:{required:!0,type:["string","number"],pattern:/^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,minimum:-100,maximum:100},port:{required:!0,type:["string","number"],pattern:/\:\d+/}};j({url:"uri",ip:"ip-address",ipv4:"ip-address",host:"host-name",hostName:"host-name"},
+function(b,c){a[b]=a[c]});return function(b,c,d,e,f){if(g(d))return this.validateProperty(b,c,d,f);if(k(d)&&!Object.prototype.hasOwnProperty.apply(a,[d]))throw Error("The format \u2018"+d+"\u2019 is not supported.");if(k(d)){d=a[d];if(t(d))return d(c)||this.addError(),f();if(g(d))return this.validateProperty(b,c,d,f)}}});f.prototype.addAttribute("length",function(a,b,c,d,e){k(b)&&b.length!==c&&this.addError();return e()});f.prototype.addAttribute("maximum",function(a,b,c,d,e){p(b)&&(d.exclusiveMaximum&&
+b>=c||b>c)&&this.addError();return e()});f.prototype.addAttribute("maxItems",function(a,b,c,d,e){h(b)&&b.length>c&&this.addError();return e()});f.prototype.addAttribute("maxLength",function(a,b,c,d,e){k(b)&&b.length>c&&this.addError();return e()});f.prototype.addAttribute("minimum",function(a,b,c,d,e){p(b)&&(d.exclusiveMinimum&&b<=c||b<c)&&this.addError();return e()});f.prototype.addAttribute("minItems",function(a,b,c,d,e){h(b)&&b.length<c&&this.addError();return e()});f.prototype.addAttribute("minLength",
+function(a,b,c,d,e){k(b)&&b.length<c&&this.addError();return e()});f.prototype.addAttribute("pattern",function(a,b,c,d,e){k(b)&&!b.match(c)&&this.addError();return e()});f.prototype.addAttribute("patternProperties",function(a,b,c,d,e){var f=this;if(m(c))return e();var l={},z=Object.keys(c);j(b,function(a){j(z,function(b,e){a.match(RegExp(e))&&(l[a]=c[e])})});if(m(l))return e();j(l,function(c,e,d){return f.validateSchema(b[c],e,f.joinPath(a,c),d)},e)});f.prototype.addAttribute("required",function(a,
+b,c,d,e){c&&(a=u(b),b=(k(b)||h(b)||g(b))&&m(b),(a||b)&&this.addError());return e()});f.prototype.addAttributeConstructor("type",function(){var a={string:k,number:p,"function":t,"boolean":B,object:g,array:h,integer:w,"int":w,"null":C,any:D};return function(b,c,d,e,f){if(h(d))d.some(function(b){if(!Object.prototype.hasOwnProperty.apply(a,[b]))throw Error("Type \u2018"+d+"\u2019 is not supported.");return a[b](c)})||this.errors.addError();else{if(!Object.prototype.hasOwnProperty.apply(a,[d]))throw Error("Type \u2018"+
+d+"\u2019 is not supported.");a[d](c)||this.addError()}return f()}});f.prototype.addAttribute("uniqueItems",function(a,b,c,d,e){var f=this;j(b,function(c,e){k(e)&&b.indexOf(e)<c&&f.addError();(g(e)||h(e))&&b.forEach(function(b,d){d!==c&&v(e,b)&&f.addError({property:f.joinPath(a,d)})})});return e()});var r=function(a){this.length=0;this.errorMessages=a.messages};r.prototype.renderErrorMessage=function(a){var b=this.errorMessages[a.attributeName];return b&&t(b)?b(a.property,a.propertyValue,a.attributeValue):
+b&&k(b)?(["property","propertyValue","attributeValue"].forEach(function(c){b=b.replace(RegExp("{{"+c+"}}","g"),a[c])}),b=b.replace(/{{validator}}/g,a.attributeValue),b.replace(/\s+/g," ")):a.message};r.prototype.push=function(a){this[this.length]={property:a.property,propertyValue:a.propertyValue,attributeName:a.attributeName,attributeValue:a.attributeValue,message:this.renderErrorMessage(a),validator:a.attributeName,validatorName:a.attributeName,validatorValue:a.attributeValue};this.length+=1};r.prototype.getProperties=
+function(){return y(this,"property")};r.prototype.getMessages=function(){return y(this,"message")};var E={required:function(a){return"The \u2018"+a+"\u2019 property is required."},minLength:function(a,b,c){return["The "+a+" property must be at least "+c+" characters.","The length of the property is "+b.length+"."].join(" ")},maxLength:function(a,b,c){return["The "+a+" property must not exceed "+c+" character"+(1<c?"s":"")+".","The length of the property is "+b.length+"."].join(" ")},length:function(a,
+b,c){return["The "+a+" property must be exactly "+c+" character"+(1<c?"s":"")+".","The length of the property is "+b.length+"."].join(" ")},format:function(a,b,c){return["The \u2018"+a+"\u2019 property must be a/an \u2018"+c+"\u2019.","The current value of the property is \u2018"+b+"\u2019"].join(" ")},type:function(a,b,c){return["The \u2018"+a+"\u2019 property must be "+(-1<"aeiou".indexOf(c[0])?"an":"a")+" \u2018"+c+"\u2019.","The type of the property is \u2018"+typeof b+"\u2019"].join(" ")},except:function(){},
+minimum:function(a,b,c){return["The minimum value of the \u2018"+a+"\u2019 must be "+c+".","The current value of the property is \u2018"+b+"\u2019"].join(" ")},maximum:function(a,b,c){return["The maximum value of the \u2018"+a+"\u2019 must be "+c+".","The current value of the property is \u2018"+b+"\u2019."].join(" ")},pattern:function(a,b,c){return"The \u2018"+a+"\u2019 does not match the \u2018"+c+"\u2019 pattern."},maxItems:function(a,b,c){return["The \u2018"+a+"\u2019 property must not contain more than \u2018"+
+c+"\u2019 items.","Currently it contains \u2018"+b.items+"\u2019 items."].join(" ")},minItems:function(a,b,c){return["The \u2018"+a+"\u2019 property must contain at least \u2018"+c+"\u2019 items.","Currently it contains \u2018"+b.items+"\u2019 items."].join(" ")},divisibleBy:function(a,b,c){return"The \u2018"+a+"\u2019 is not divisible by \u2018"+c+"\u2019."},uniqueItems:function(a){return"All items in the \u2018"+a+"\u2019 property must be unique."},"enum":function(a,b,c){return"Value of the \u2018"+
+a+"\u2019 must be "+c.join(" or ")+"."}};f.prototype.getProperty=function(a,b){if(b)return b[a]?b[a]:void 0};f.prototype.joinPath=function(a,b){a=a||"";b+="";return b.match(/^[a-zA-Z][a-zA-Z0-9]*$/)?a?a+"."+b:b:b.match(/\d+/)?a+"["+b+"]":a+'["'+b+'"]'};f.prototype.validate=function(a,b,c){var d=this;this.instance=a;this.schema=b;var e=function(){return 0!==d.errors.length?c(d.errors):c()};if(-1!=="string number function boolean integer int null".split(" ").indexOf(b.type))return this.validateProperty(void 0,
+a,b,e);if(-1!==["object","array"].indexOf(b.type)){if(k(a))try{a=JSON.parse(a)}catch(f){}return this.validateSchema(a,b,"",e)}if("any"===b.type||!b.type){if(k(a))try{return a=JSON.parse(a),this.validateSchema(a,b,"",e)}catch(l){}return g(a)||h(a)?this.validateSchema(a,b,"",e):this.validateProperty(void 0,a,b,e)}};f.prototype.validateItems=function(a,b,c,d){var e=this;return h(b.items)?u(b.additionalItems)||!0===b.additionalItems?j(b.items,function(b,d,f){return e.validateSchema(a[b],d,e.joinPath(c,
+b),f)},d):j(a,function(a,d,f){if(b.items[a]||g(b.additionalItems))return e.validateSchema(d,b.items[a],e.joinPath(c,a),f);if(!1===b.additionalItems)return e.errors.push({property:e.joinPath(c,a),propertyValue:d,attributeName:"additionalItems",attributeValue:!1}),f()},d):g(b.items)&&a&&!m(a)?j(a,function(d,f,g){return e.validateSchema(a[d],b.items,e.joinPath(c,d),g)},d):d()};f.prototype.validateProperties=function(a,b,c,d){var e=this;return j(b.properties,function(d,f,g){var k="object"===f.type&&f.properties,
+h="array"===f.type,j=e.getProperty(d,a),s=e.joinPath(c,d);return k||h?e.validateSchema(j,b.properties[d],s,g):e.validateProperty(s,j,f,g)},d)};f.prototype.validateProperty=function(a,b,c,d){var e=this,f={};"validateItems validateProperties validateSchema validateProperty getProperty attributes errors joinPath".split(" ").forEach(function(a){f[a]=this[a]},e);return!0!==c.required&&u(b)?d():j(e.attributes,function(d,j,h){var m=e.errors.length;f.addError=function(f){return g(f)?e.errors.push({property:f.property||
+a,propertyValue:f.propertyValue||b,attributeName:f.attributeName||d,attributeValue:f.attributeValue||c[d],message:f.message||void 0}):e.errors.push({property:a,propertyValue:b,attributeName:d,attributeValue:c[d],message:f})};var n=function(a){return!0===a||k(a)?(f.addError(a),h(!0)):e.errors.length>m&&e.singleError?h(!0):h()};return"undefined"!==typeof c[d]?j.apply(f,[a,b,c[d],c,n]):h()},d)};f.prototype.validateSchema=function(a,b,c,d){var e=this;return e.validateProperty(c,a,b,function(){return b.properties?
+e.validateProperties(a,b,c,d):b.items?e.validateItems(a,b,c,d):d()})};n.json={validate:function(a,b,c,d){"function"===typeof c&&(d=c,c={});return(new f(c)).validate(a,b,d)},addAttribute:function(a,b){return f.prototype.addAttribute.apply(f,arguments)},addAttributeConstructor:function(a,b){return f.prototype.addAttributeConstructor.apply(f,arguments)}};var q=function(a){if(!Object.prototype.hasOwnProperty.apply(n,[a]))throw Error("The \u2018"+a+"\u2019 engine is not supported. Please use a different one.");
+return n[a]};q.validate=function(a,b,c,d){var e=n.json;return e.validate.apply(e,arguments)};q.addValidator=function(a,b){var c=n.json;return c.addAttribute.apply(c,arguments)};q.addAttribute=function(a,b){var c=n.json;return c.addAttribute.apply(c,arguments)};q.addAttributeConstructor=function(a,b){var c=n.json;return c.addAttributeConstructor.apply(c,arguments)};"undefined"!==typeof module&&module.exports?module.exports=q:"undefined"!==typeof define?define(function(){return q}):this.amanda=q})();
View
3,212 releases/latest/amanda.js
1,646 additions, 1,566 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
50 releases/latest/amanda.min.js
@@ -1,26 +1,26 @@
-(function(){var p={},n=function(a,g,h){var f=function(b,f,a){var c=[],j=function(b,i){var j=c.length+1;c.push(function(){return f(b,i,function(b){var f=c[j];return!b&&f?f():!b&&!f?a():a(b)})})};if(l(b)&&!o(b))for(var i=0,g=b.length;i<g;i++)j(i,b[i]);else if(k(b)&&!o(b))for(i in b)b.hasOwnProperty(i)&&j(i,b[i]);else return a();return c[0]()};return"undefined"===typeof h?function(b,f){if(l(b)&&!o(b))for(var a=0,c=b.length;a<c;a++)f.apply(b,[a,b[a]]);if(k(b)&&!o(b))for(var j in b)b.hasOwnProperty(j)&&
-f.apply(b,[j,b[j]])}.apply(this,arguments):f.apply(this,arguments)},A=function(a,g,h){return Array.prototype.filter.apply(a,[g,h||this])},l=function(a){return"[object Array]"===Object.prototype.toString.call(a)},B=function(a){return"boolean"===typeof a},s=function(a){return"undefined"!==typeof a},o=function(a){if(q(a))return!1;if(null===a)return!0;if(l(a)||"string"===typeof a)return 0===a.length;if(k(a))for(var g in a)if(hasOwnProperty.call(a,g))return!1;return!0},w=function(a,g){if(l(a,g))return a.length!==
-g.length?!1:Array.prototype.every.apply(a,[function(b,f){return g[f]===b}]);if(k(a,g)){var h=Object.keys(a),f=Object.keys(g);if(!w(h,f))return!1;for(key in a)if(!g[key]||a[key]!==g[key])return!1;return!0}return!1},t=function(a){return"function"===typeof a},x=function(a){return q(a)&&0===a%1},C=function(a){return null===a},q=function(a){return"number"===typeof a},k=function(a){return"[object Object]"===Object.prototype.toString.call(a)},m=function(a){return"string"===typeof a},u=function(a){return"undefined"===
-typeof a},y=function(a,g){for(var h in g)g.hasOwnProperty(h)&&!a.hasOwnProperty(h)&&(a[h]=g[h]);return a},z=function(a,g){for(var h=[],f=0,b=a.length;f<b;f++){var d=a[f][g];-1===h.indexOf(d)&&h.push(d)}return h},D=function(){return!0};(function(){var a=function(f){var b=this,d={singleError:!0,messages:h,cache:!1};n(d,function(a,c){b[a]=k(c)&&f[a]?y(f[a],d[a]):k(c)&&!f[a]?y({},d[a]):s(f[a])?f[a]:d[a]});this.errors=new g(this)};a.prototype.attributes={};a.prototype.addAttribute=function(f,b){return a.prototype.attributes[f]=
-b};a.prototype.addAttributeConstructor=function(f,b){return a.prototype.attributes[f]=b()};a.prototype.addAttribute("additionalProperties",function(f,b,d,a,c){var j=this;if(!0===d)return c();var i=Object.keys(b),i=A(i,function(b){return!a.properties[b]});if(o(i))return c();if(!1===d)return i.forEach(function(a){this.addError({property:this.joinPath(f,a),propertyValue:b[a]})},this),c();if(k(d))return n(i,function(a,c,e){return j.validateSchema(b[c],d,f+c,e)},c)});a.prototype.addAttribute("divisibleBy",
-function(f,b,a,e,c){if(0===a)throw Error("The value of this attribute should not be 0.");q(b)&&0!==b%a&&this.addError();return c()});a.prototype.addAttribute("enum",function(f,b,a,e,c){-1===a.indexOf(b)&&this.addError();return c()});a.prototype.addAttribute("except",function(f,b,a,e,c){-1!==a.indexOf(b)&&this.addError();return c()});a.prototype.addAttributeConstructor("format",function(){var f={"date-time":{type:"string",pattern:/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/},
-date:function(b){return m(b)?b.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/):k(b)?"[object Date]"===Object.prototype.toString.call(b):!1},time:{type:"string",pattern:/^\d{2}:\d{2}:\d{2}$/},"utc-milisec":{type:"number"},regex:function(b){return b&&b.test&&b.exec},color:{type:"string"},style:{type:"string"},phone:{type:"number"},uri:{type:"string",pattern:/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/},
+(function(){var n={},j=function(a,b,c){var d=function(a,b){if(h(a)&&!m(a))for(var c=0,e=a.length;c<e;c++)b.apply(a,[c,a[c]]);if(g(a)&&!m(a))for(var d in a)a.hasOwnProperty(d)&&b.apply(a,[d,a[d]])},e=function(a,b,c){var e=[],d=function(a,d){var f=e.length+1;e.push(function(){return b(a,d,function(a){var b=e[f];return!a&&b?b():!a&&!b?c():c(a)})})};if(h(a)&&!m(a))for(var f=0,s=a.length;f<s;f++)d(f,a[f]);else if(g(a)&&!m(a))for(f in a)a.hasOwnProperty(f)&&d(f,a[f]);else return c();return e[0]()};return"undefined"===
+typeof c?d.apply(this,arguments):e.apply(this,arguments)},A=function(a,b,c){return Array.prototype.filter.apply(a,[b,c||this])},h=function(a){return"[object Array]"===Object.prototype.toString.call(a)},B=function(a){return"boolean"===typeof a},m=function(a){if(p(a))return!1;if(null===a)return!0;if(h(a)||"string"===typeof a)return 0===a.length;if(g(a))for(var b in a)if(hasOwnProperty.call(a,b))return!1;return!0},v=function(a,b){if(h(a,b))return a.length!==b.length?!1:Array.prototype.every.apply(a,
+[function(a,c){return b[c]===a}]);if(g(a,b)){var c=Object.keys(a),d=Object.keys(b);if(!v(c,d))return!1;for(key in a)if(!b[key]||a[key]!==b[key])return!1;return!0}return!1},t=function(a){return"function"===typeof a},w=function(a){return p(a)&&0===a%1},C=function(a){return null===a},p=function(a){return"number"===typeof a},g=function(a){return"[object Object]"===Object.prototype.toString.call(a)},k=function(a){return"string"===typeof a},u=function(a){return"undefined"===typeof a},x=function(a,b){for(var c in b)b.hasOwnProperty(c)&&
+!a.hasOwnProperty(c)&&(a[c]=b[c]);return a},y=function(a,b){for(var c=[],d=0,e=a.length;d<e;d++){var f=a[d][b];-1===c.indexOf(f)&&c.push(f)}return c},D=function(){return!0},f=function(a){var b=this,c={singleError:!0,messages:E,cache:!1};j(c,function(d,e){b[d]=g(e)&&a[d]?x(a[d],c[d]):g(e)&&!a[d]?x({},c[d]):"undefined"!==typeof a[d]?a[d]:c[d]});this.errors=new r(this)};f.prototype.attributes={};f.prototype.addAttribute=function(a,b){return f.prototype.attributes[a]=b};f.prototype.addAttributeConstructor=
+function(a,b){return f.prototype.attributes[a]=b()};f.prototype.addAttribute("additionalProperties",function(a,b,c,d,e){var f=this;if(!0===c)return e();var l=Object.keys(b),l=A(l,function(a){return!d.properties[a]});if(m(l))return e();if(!1===c)return l.forEach(function(c){this.addError({property:this.joinPath(a,c),propertyValue:b[c]})},this),e();if(g(c))return j(l,function(d,e,l){return f.validateSchema(b[e],c,a+e,l)},e)});f.prototype.addAttribute("divisibleBy",function(a,b,c,d,e){if(0===c)throw Error("The value of this attribute should not be 0.");
+p(b)&&0!==b%c&&this.addError();return e()});f.prototype.addAttribute("enum",function(a,b,c,d,e){-1===c.indexOf(b)&&this.addError();return e()});f.prototype.addAttribute("except",function(a,b,c,d,e){-1!==c.indexOf(b)&&this.addError();return e()});f.prototype.addAttributeConstructor("format",function(){var a={"date-time":{type:"string",pattern:/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/},date:function(a){return k(a)?a.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/):g(a)?"[object Date]"===
+Object.prototype.toString.call(a):!1},time:{type:"string",pattern:/^\d{2}:\d{2}:\d{2}$/},"utc-milisec":{type:"number"},regex:function(a){return a&&a.test&&a.exec},color:{type:"string"},style:{type:"string"},phone:{type:"number"},uri:{type:"string",pattern:/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]