summaryrefslogtreecommitdiff
path: root/node_modules/revalidator/lib/revalidator.js
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2021-12-21 16:50:49 +0100
committerMinteck <contact@minteck.org>2021-12-21 16:50:49 +0100
commit20204baf1807825af4798ad03bfb329e4da05bc5 (patch)
tree1568515fa1e4592206ed5d2327b39e6b443cbd03 /node_modules/revalidator/lib/revalidator.js
downloadbingoloto-remote-20204baf1807825af4798ad03bfb329e4da05bc5.tar.gz
bingoloto-remote-20204baf1807825af4798ad03bfb329e4da05bc5.tar.bz2
bingoloto-remote-20204baf1807825af4798ad03bfb329e4da05bc5.zip
Commit
Diffstat (limited to 'node_modules/revalidator/lib/revalidator.js')
-rw-r--r--node_modules/revalidator/lib/revalidator.js427
1 files changed, 427 insertions, 0 deletions
diff --git a/node_modules/revalidator/lib/revalidator.js b/node_modules/revalidator/lib/revalidator.js
new file mode 100644
index 0000000..ad65814
--- /dev/null
+++ b/node_modules/revalidator/lib/revalidator.js
@@ -0,0 +1,427 @@
+(function (exports) {
+ exports.validate = validate;
+ exports.mixin = mixin;
+
+ //
+ // ### function validate (object, schema, options)
+ // #### {Object} object the object to validate.
+ // #### {Object} schema (optional) the JSON Schema to validate against.
+ // #### {Object} options (optional) options controlling the validation
+ // process. See {@link #validate.defaults) for details.
+ // Validate <code>object</code> against a JSON Schema.
+ // If <code>object</code> is self-describing (i.e. has a
+ // <code>$schema</code> property), it will also be validated
+ // against the referenced schema. [TODO]: This behaviour bay be
+ // suppressed by setting the {@link #validate.options.???}
+ // option to <code>???</code>.[/TODO]
+ //
+ // If <code>schema</code> is not specified, and <code>object</code>
+ // is not self-describing, validation always passes.
+ //
+ // <strong>Note:</strong> in order to pass options but no schema,
+ // <code>schema</code> <em>must</em> be specified in the call to
+ // <code>validate()</code>; otherwise, <code>options</code> will
+ // be interpreted as the schema. <code>schema</code> may be passed
+ // as <code>null</code>, <code>undefinded</code>, or the empty object
+ // (<code>{}</code>) in this case.
+ //
+ function validate(object, schema, options) {
+ options = mixin({}, options, validate.defaults);
+ var errors = [];
+
+ validateObject(object, schema, options, errors);
+
+ //
+ // TODO: self-described validation
+ // if (! options.selfDescribing) { ... }
+ //
+
+ return {
+ valid: !(errors.length),
+ errors: errors
+ };
+ };
+
+ /**
+ * Default validation options. Defaults can be overridden by
+ * passing an 'options' hash to {@link #validate}. They can
+ * also be set globally be changing the values in
+ * <code>validate.defaults</code> directly.
+ */
+ validate.defaults = {
+ /**
+ * <p>
+ * Enforce 'format' constraints.
+ * </p><p>
+ * <em>Default: <code>true</code></em>
+ * </p>
+ */
+ validateFormats: true,
+ /**
+ * <p>
+ * When {@link #validateFormats} is <code>true</code>,
+ * treat unrecognized formats as validation errors.
+ * </p><p>
+ * <em>Default: <code>false</code></em>
+ * </p>
+ *
+ * @see validation.formats for default supported formats.
+ */
+ validateFormatsStrict: false,
+ /**
+ * <p>
+ * When {@link #validateFormats} is <code>true</code>,
+ * also validate formats defined in {@link #validate.formatExtensions}.
+ * </p><p>
+ * <em>Default: <code>true</code></em>
+ * </p>
+ */
+ validateFormatExtensions: true
+ };
+
+ /**
+ * Default messages to include with validation errors.
+ */
+ validate.messages = {
+ required: "is required",
+ allowEmpty: "must not be empty",
+ minLength: "is too short (minimum is %{expected} characters)",
+ maxLength: "is too long (maximum is %{expected} characters)",
+ pattern: "invalid input",
+ minimum: "must be greater than or equal to %{expected}",
+ maximum: "must be less than or equal to %{expected}",
+ exclusiveMinimum: "must be greater than %{expected}",
+ exclusiveMaximum: "must be less than %{expected}",
+ divisibleBy: "must be divisible by %{expected}",
+ minItems: "must contain more than %{expected} items",
+ maxItems: "must contain less than %{expected} items",
+ uniqueItems: "must hold a unique set of values",
+ format: "is not a valid %{expected}",
+ conform: "must conform to given constraint",
+ type: "must be of %{expected} type"
+ };
+ validate.messages['enum'] = "must be present in given enumerator";
+
+ /**
+ *
+ */
+ validate.formats = {
+ 'email': /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i,
+ 'ip-address': /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i,
+ 'ipv6': /^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/,
+ 'date-time': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d{1,3})?Z$/,
+ 'date': /^\d{4}-\d{2}-\d{2}$/,
+ 'time': /^\d{2}:\d{2}:\d{2}$/,
+ 'color': /^#[a-z0-9]{6}|#[a-z0-9]{3}|(?:rgb\(\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*\))aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow$/i,
+ //'style': (not supported)
+ //'phone': (not supported)
+ //'uri': (not supported)
+ 'host-name': /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])/,
+ 'utc-millisec': {
+ test: function (value) {
+ return typeof(value) === 'number' && value >= 0;
+ }
+ },
+ 'regex': {
+ test: function (value) {
+ try { new RegExp(value) }
+ catch (e) { return false }
+
+ return true;
+ }
+ }
+ };
+
+ /**
+ *
+ */
+ validate.formatExtensions = {
+ 'url': /^(https?|ftp|git):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i
+ };
+
+ function mixin(obj) {
+ var sources = Array.prototype.slice.call(arguments, 1);
+ while (sources.length) {
+ var source = sources.shift();
+ if (!source) { continue }
+
+ if (typeof(source) !== 'object') {
+ throw new TypeError('mixin non-object');
+ }
+
+ for (var p in source) {
+ if (source.hasOwnProperty(p)) {
+ obj[p] = source[p];
+ }
+ }
+ }
+
+ return obj;
+ };
+
+ function validateObject(object, schema, options, errors) {
+ var props, allProps = Object.keys(object),
+ visitedProps = [];
+
+ // see 5.2
+ if (schema.properties) {
+ props = schema.properties;
+ for (var p in props) {
+ if (props.hasOwnProperty(p)) {
+ visitedProps.push(p);
+ validateProperty(object, object[p], p, props[p], options, errors);
+ }
+ }
+ }
+
+ // see 5.3
+ if (schema.patternProperties) {
+ props = schema.patternProperties;
+ for (var p in props) {
+ if (props.hasOwnProperty(p)) {
+ var re = new RegExp(p);
+
+ // Find all object properties that are matching `re`
+ for (var k in object) {
+ if (object.hasOwnProperty(k)) {
+ visitedProps.push(k);
+ if (re.exec(k) !== null) {
+ validateProperty(object, object[k], p, props[p], options, errors);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // see 5.4
+ if (undefined !== schema.additionalProperties) {
+ var i, l;
+
+ var unvisitedProps = allProps.filter(function(k){
+ return -1 === visitedProps.indexOf(k);
+ });
+
+ // Prevent additional properties; each unvisited property is therefore an error
+ if (schema.additionalProperties === false && unvisitedProps.length > 0) {
+ for (i = 0, l = unvisitedProps.length; i < l; i++) {
+ error("additionalProperties", unvisitedProps[i], object[unvisitedProps[i]], false, errors);
+ }
+ }
+ // additionalProperties is a schema and validate unvisited properties against that schema
+ else if (typeof schema.additionalProperties == "object" && unvisitedProps.length > 0) {
+ for (i = 0, l = unvisitedProps.length; i < l; i++) {
+ validateProperty(object, object[unvisitedProps[i]], unvisitedProps[i], schema.unvisitedProperties, options, errors);
+ }
+ }
+ }
+
+ };
+
+ function validateProperty(object, value, property, schema, options, errors) {
+ var format,
+ valid,
+ spec,
+ type;
+
+ function constrain(name, value, assert) {
+ if (schema[name] !== undefined && !assert(value, schema[name])) {
+ error(name, property, value, schema, errors);
+ }
+ }
+
+ if (value === undefined) {
+ if (schema.required && schema.type !== 'any') {
+ return error('required', property, undefined, schema, errors);
+ } else {
+ return;
+ }
+ }
+
+ if (options.cast) {
+ if (('integer' === schema.type || 'number' === schema.type) && value == +value) {
+ value = +value;
+ object[property] = value;
+ }
+
+ if ('boolean' === schema.type) {
+ if ('true' === value || '1' === value || 1 === value) {
+ value = true;
+ object[property] = value;
+ }
+
+ if ('false' === value || '0' === value || 0 === value) {
+ value = false;
+ object[property] = value;
+ }
+ }
+ }
+
+ if (schema.format && options.validateFormats) {
+ format = schema.format;
+
+ if (options.validateFormatExtensions) { spec = validate.formatExtensions[format] }
+ if (!spec) { spec = validate.formats[format] }
+ if (!spec) {
+ if (options.validateFormatsStrict) {
+ return error('format', property, value, schema, errors);
+ }
+ }
+ else {
+ if (!spec.test(value)) {
+ return error('format', property, value, schema, errors);
+ }
+ }
+ }
+
+ if (schema['enum'] && schema['enum'].indexOf(value) === -1) {
+ error('enum', property, value, schema, errors);
+ }
+
+ // Dependencies (see 5.8)
+ if (typeof schema.dependencies === 'string' &&
+ object[schema.dependencies] === undefined) {
+ error('dependencies', property, null, schema, errors);
+ }
+
+ if (isArray(schema.dependencies)) {
+ for (var i = 0, l = schema.dependencies.length; i < l; i++) {
+ if (object[schema.dependencies[i]] === undefined) {
+ error('dependencies', property, null, schema, errors);
+ }
+ }
+ }
+
+ if (typeof schema.dependencies === 'object') {
+ validateObject(object, schema.dependencies, options, errors);
+ }
+
+ checkType(value, schema.type, function(err, type) {
+ if (err) return error('type', property, typeof value, schema, errors);
+
+ constrain('conform', value, function (a, e) { return e(a, object) });
+
+ switch (type || (isArray(value) ? 'array' : typeof value)) {
+ case 'string':
+ constrain('allowEmpty', value, function (a, e) { return e ? e : a !== '' });
+ constrain('minLength', value.length, function (a, e) { return a >= e });
+ constrain('maxLength', value.length, function (a, e) { return a <= e });
+ constrain('pattern', value, function (a, e) {
+ e = typeof e === 'string'
+ ? e = new RegExp(e)
+ : e;
+ return e.test(a)
+ });
+ break;
+ case 'integer':
+ case 'number':
+ constrain('minimum', value, function (a, e) { return a >= e });
+ constrain('maximum', value, function (a, e) { return a <= e });
+ constrain('exclusiveMinimum', value, function (a, e) { return a > e });
+ constrain('exclusiveMaximum', value, function (a, e) { return a < e });
+ constrain('divisibleBy', value, function (a, e) {
+ var multiplier = Math.max((a - Math.floor(a)).toString().length - 2, (e - Math.floor(e)).toString().length - 2);
+ multiplier = multiplier > 0 ? Math.pow(10, multiplier) : 1;
+ return (a * multiplier) % (e * multiplier) === 0
+ });
+ break;
+ case 'array':
+ constrain('items', value, function (a, e) {
+ for (var i = 0, l = a.length; i < l; i++) {
+ validateProperty(object, a[i], property, e, options, errors);
+ }
+ return true;
+ });
+ constrain('minItems', value, function (a, e) { return a.length >= e });
+ constrain('maxItems', value, function (a, e) { return a.length <= e });
+ constrain('uniqueItems', value, function (a) {
+ var h = {};
+
+ for (var i = 0, l = a.length; i < l; i++) {
+ var key = JSON.stringify(a[i]);
+ if (h[key]) return false;
+ h[key] = true;
+ }
+
+ return true;
+ });
+ break;
+ case 'object':
+ // Recursive validation
+ if (schema.properties || schema.patternProperties || schema.additionalProperties) {
+ validateObject(value, schema, options, errors);
+ }
+ break;
+ }
+ });
+ };
+
+ function checkType(val, type, callback) {
+ var result = false,
+ types = isArray(type) ? type : [type];
+
+ // No type - no check
+ if (type === undefined) return callback(null, type);
+
+ // Go through available types
+ // And fine first matching
+ for (var i = 0, l = types.length; i < l; i++) {
+ type = types[i].toLowerCase().trim();
+ if (type === 'string' ? typeof val === 'string' :
+ type === 'array' ? isArray(val) :
+ type === 'object' ? val && typeof val === 'object' &&
+ !isArray(val) :
+ type === 'number' ? typeof val === 'number' :
+ type === 'integer' ? typeof val === 'number' && ~~val === val :
+ type === 'null' ? val === null :
+ type === 'boolean'? typeof val === 'boolean' :
+ type === 'date' ? isDate(val) :
+ type === 'any' ? typeof val !== 'undefined' : false) {
+ return callback(null, type);
+ }
+ };
+
+ callback(true);
+ };
+
+ function error(attribute, property, actual, schema, errors) {
+ var lookup = { expected: schema[attribute], actual: actual, attribute: attribute, property: property };
+ var message = schema.messages && schema.messages[attribute] || schema.message || validate.messages[attribute] || "no default message";
+ message = message.replace(/%\{([a-z]+)\}/ig, function (_, match) { return lookup[match.toLowerCase()] || ''; });
+ errors.push({
+ attribute: attribute,
+ property: property,
+ expected: schema[attribute],
+ actual: actual,
+ message: message
+ });
+ };
+
+ function isArray(value) {
+ var s = typeof value;
+ if (s === 'object') {
+ if (value) {
+ if (typeof value.length === 'number' &&
+ !(value.propertyIsEnumerable('length')) &&
+ typeof value.splice === 'function') {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function isDate(value) {
+ var s = typeof value;
+ if (s === 'object') {
+ if (value) {
+ if (typeof value.getTime === 'function') {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+})(typeof module === 'object' && module && module.exports ? module.exports : window);