summaryrefslogtreecommitdiff
path: root/node_modules/revalidator
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/revalidator')
-rw-r--r--node_modules/revalidator/.npmignore2
-rw-r--r--node_modules/revalidator/.travis.yml11
-rw-r--r--node_modules/revalidator/CHANGELOG.md25
-rw-r--r--node_modules/revalidator/LICENSE179
-rw-r--r--node_modules/revalidator/README.md301
-rw-r--r--node_modules/revalidator/example/webservice.js204
-rw-r--r--node_modules/revalidator/lib/revalidator.js427
-rw-r--r--node_modules/revalidator/package.json63
-rw-r--r--node_modules/revalidator/test/validator-test.js421
9 files changed, 1633 insertions, 0 deletions
diff --git a/node_modules/revalidator/.npmignore b/node_modules/revalidator/.npmignore
new file mode 100644
index 0000000..5171c54
--- /dev/null
+++ b/node_modules/revalidator/.npmignore
@@ -0,0 +1,2 @@
+node_modules
+npm-debug.log \ No newline at end of file
diff --git a/node_modules/revalidator/.travis.yml b/node_modules/revalidator/.travis.yml
new file mode 100644
index 0000000..04d6dd9
--- /dev/null
+++ b/node_modules/revalidator/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+ - "0.8"
+ - "0.10"
+ - "0.11"
+
+notifications:
+ email:
+ - travis@nodejitsu.com
+ irc: "irc.freenode.org#nodejitsu"
+
diff --git a/node_modules/revalidator/CHANGELOG.md b/node_modules/revalidator/CHANGELOG.md
new file mode 100644
index 0000000..8befb22
--- /dev/null
+++ b/node_modules/revalidator/CHANGELOG.md
@@ -0,0 +1,25 @@
+
+0.1.3 / 2012-10-17
+==================
+
+ * Fixed case problem with types
+
+0.1.2 / 2012-06-27
+==================
+
+ * Added host-name String format
+ * Added support for additionalProperties
+ * Added few default validation messages for formats
+
+0.1.1 / 2012-04-16
+==================
+
+ * Added default and custom error message support
+ * Added suport for conform function
+ * Updated date-time format
+
+0.1.0 / 2011-11-09
+=================
+
+ * Initial release
+
diff --git a/node_modules/revalidator/LICENSE b/node_modules/revalidator/LICENSE
new file mode 100644
index 0000000..a83d179
--- /dev/null
+++ b/node_modules/revalidator/LICENSE
@@ -0,0 +1,179 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+Copyright (c) 2009-2010 Alexis Sellier, Charlie Robbins, Nodejitsu Inc.
diff --git a/node_modules/revalidator/README.md b/node_modules/revalidator/README.md
new file mode 100644
index 0000000..be6601b
--- /dev/null
+++ b/node_modules/revalidator/README.md
@@ -0,0 +1,301 @@
+# revalidator [![Build Status](https://secure.travis-ci.org/flatiron/revalidator.png)](http://travis-ci.org/flatiron/revalidator)
+
+A cross-browser / node.js validator used by resourceful and flatiron. Revalidator has [JSONSchema](http://tools.ietf.org/html/draft-zyp-json-schema-04) compatibility as primary goal.
+
+## Example
+The core of `revalidator` is simple and succinct: `revalidator.validate(obj, schema)`:
+
+``` js
+ var revalidator = require('revalidator');
+
+ console.dir(revalidator.validate(someObject, {
+ properties: {
+ url: {
+ description: 'the url the object should be stored at',
+ type: 'string',
+ pattern: '^/[^#%&*{}\\:<>?\/+]+$',
+ required: true
+ },
+ challenge: {
+ description: 'a means of protecting data (insufficient for production, used as example)',
+ type: 'string',
+ minLength: 5
+ },
+ body: {
+ description: 'what to store at the url',
+ type: 'any',
+ default: null
+ }
+ }
+ }));
+```
+
+This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation.
+
+``` js
+ {
+ valid: true // or false
+ errors: [/* Array of errors if valid is false */]
+ }
+```
+
+In the browser, the validation function is exposed on `window.validate` by simply including `revalidator.js`.
+
+## Installation
+
+### Installing npm (node package manager)
+``` bash
+ $ curl http://npmjs.org/install.sh | sh
+```
+
+### Installing revalidator
+``` bash
+ $ [sudo] npm install revalidator
+```
+
+## Usage
+
+`revalidator` takes json-schema as input to validate objects.
+
+### revalidator.validate (obj, schema, options)
+
+This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation.
+
+``` js
+{
+ valid: true // or false
+ errors: [/* Array of errors if valid is false */]
+}
+```
+
+#### Available Options
+
+* __validateFormats__: Enforce format constraints (_default true_)
+* __validateFormatsStrict__: When `validateFormats` is _true_ treat unrecognized formats as validation errors (_default false_)
+* __validateFormatExtensions__: When `validateFormats` is _true_ also validate formats defined in `validate.formatExtensions` (_default true_)
+* __cast__: Enforce casting of some types (for integers/numbers are only supported) when it's possible, e.g. `"42" => 42`, but `"forty2" => "forty2"` for the `integer` type.
+
+### Schema
+For a property an `value` is that which is given as input for validation where as an `expected value` is the value of the below fields
+
+#### required
+If true, the value should not be undefined
+
+```js
+{ required: true }
+```
+
+#### allowEmpty
+If false, the value must not be an empty string
+
+```js
+{ allowEmpty: false }
+```
+
+#### type
+The `type of value` should be equal to the expected value
+
+```js
+{ type: 'string' }
+{ type: 'number' }
+{ type: 'integer' }
+{ type: 'array' }
+{ type: 'boolean' }
+{ type: 'object' }
+{ type: 'null' }
+{ type: 'any' }
+{ type: ['boolean', 'string'] }
+```
+
+#### pattern
+The expected value regex needs to be satisfied by the value
+
+```js
+{ pattern: /^[a-z]+$/ }
+```
+
+#### maxLength
+The length of value must be greater than or equal to expected value
+
+```js
+{ maxLength: 8 }
+```
+
+#### minLength
+The length of value must be lesser than or equal to expected value
+
+```js
+{ minLength: 8 }
+```
+
+#### minimum
+Value must be greater than or equal to the expected value
+
+```js
+{ minimum: 10 }
+```
+
+#### maximum
+Value must be lesser than or equal to the expected value
+
+```js
+{ maximum: 10 }
+```
+
+#### allowEmpty
+Value may not be empty
+
+```js
+{ allowEmpty: false }
+```
+
+#### exclusiveMinimum
+Value must be greater than expected value
+
+```js
+{ exclusiveMinimum: 9 }
+```
+
+### exclusiveMaximum
+Value must be lesser than expected value
+
+```js
+{ exclusiveMaximum: 11 }
+```
+
+#### divisibleBy
+Value must be divisible by expected value
+
+```js
+{ divisibleBy: 5 }
+{ divisibleBy: 0.5 }
+```
+
+#### minItems
+Value must contain more then expected value number of items
+
+```js
+{ minItems: 2 }
+```
+
+#### maxItems
+Value must contains less then expected value number of items
+
+```js
+{ maxItems: 5 }
+```
+
+#### uniqueItems
+Value must hold a unique set of values
+
+```js
+{ uniqueItems: true }
+```
+
+#### enum
+Value must be present in the array of expected value
+
+```js
+{ enum: ['month', 'year'] }
+```
+
+#### format
+Value must be a valid format
+
+```js
+{ format: 'url' }
+{ format: 'email' }
+{ format: 'ip-address' }
+{ format: 'ipv6' }
+{ format: 'date-time' }
+{ format: 'date' }
+{ format: 'time' }
+{ format: 'color' }
+{ format: 'host-name' }
+{ format: 'utc-millisec' }
+{ format: 'regex' }
+```
+
+#### conform
+Value must conform to constraint denoted by expected value
+
+```js
+{ conform: function (v) {
+ if (v%3==1) return true;
+ return false;
+ }
+}
+```
+
+#### dependencies
+Value is valid only if the dependent value is valid
+
+```js
+{
+ town: { required: true, dependencies: 'country' },
+ country: { maxLength: 3, required: true }
+}
+```
+
+### Nested Schema
+We also allow nested schema
+
+```js
+{
+ properties: {
+ title: {
+ type: 'string',
+ maxLength: 140,
+ required: true
+ },
+ author: {
+ type: 'object',
+ required: true,
+ properties: {
+ name: {
+ type: 'string',
+ required: true
+ },
+ email: {
+ type: 'string',
+ format: 'email'
+ }
+ }
+ }
+ }
+}
+```
+
+### Custom Messages
+We also allow custom message for different constraints
+
+```js
+{
+ type: 'string',
+ format: 'url'
+ messages: {
+ type: 'Not a string type',
+ format: 'Expected format is a url'
+ }
+```
+
+```js
+{
+ conform: function () { ... },
+ message: 'This can be used as a global message'
+}
+```
+
+## Tests
+All tests are written with [vows][0] and should be run with [npm][1]:
+
+``` bash
+ $ npm test
+```
+
+#### Author: [Charlie Robbins](http://nodejitsu.com), [Alexis Sellier](http://cloudhead.io)
+#### Contributors: [Fedor Indutny](http://github.com/indutny), [Bradley Meck](http://github.com/bmeck), [Laurie Harper](http://laurie.holoweb.net/)
+#### License: Apache 2.0
+
+[0]: http://vowsjs.org
+[1]: http://npmjs.org
diff --git a/node_modules/revalidator/example/webservice.js b/node_modules/revalidator/example/webservice.js
new file mode 100644
index 0000000..33d5f0e
--- /dev/null
+++ b/node_modules/revalidator/example/webservice.js
@@ -0,0 +1,204 @@
+//
+// (C) 2011, Nodejitsu Inc.
+// MIT License
+//
+// A simple web service for storing JSON data via REST
+//
+// GET - View Object
+// POST - Create Object
+// PUT - Update Object
+// DELETE - Delete Object
+//
+
+var revalidator = require('../'),
+ http = require('http'),
+//
+// Keep our objects in a simple memory store
+//
+ memoryStore = {},
+//
+// Set up our request schema
+//
+ schema = {
+ properties: {
+ url: {
+ description: 'the url the object should be stored at',
+ type: 'string',
+ pattern: '^/[^#%&*{}\\:<>?\/+]+$',
+ required: true
+ },
+ challenge: {
+ description: 'a means of protecting data (insufficient for production, used as example)',
+ type: 'string',
+ minLength: 5
+ },
+ body: {
+ description: 'what to store at the url',
+ type: 'any',
+ default: null
+ }
+ }
+ }
+
+var server = http.createServer(function validateRestRequest (req, res) {
+ req.method = req.method.toUpperCase();
+
+ //
+ // Log the requests
+ //
+ console.log(req.method, req.url);
+
+ //
+ // Buffer the request so it can be parsed as JSON
+ //
+ var requestBody = [];
+ req.on('data', function addDataToBody (data) {
+ requestBody.push(data);
+ });
+
+ //
+ // Once the request has ended work with the body
+ //
+ req.on('end', function dealWithRest () {
+
+ //
+ // Parse the JSON
+ //
+ requestBody = requestBody.join('');
+ if ({POST: 1, PUT: 1}[req.method]) {
+ try {
+ requestBody = JSON.parse(requestBody);
+ }
+ catch (e) {
+ res.writeHead(400);
+ res.end(e);
+ return;
+ }
+ }
+ else {
+ requestBody = {};
+ }
+
+ //
+ // If this was sent to a url but the body url was not declared
+ // Make sure the body get the requested url so that our schema
+ // validates before we work on it
+ //
+ if (!requestBody.url) {
+ requestBody.url = req.url;
+ }
+
+ //
+ // Don't let users override the main API endpoint
+ //
+ if (requestBody.url === '/') {
+ res.writeHead(400);
+ res.end('Cannot override the API endpoint "/"');
+ return;
+ }
+
+ //
+ // See if our request and target are out of sync
+ // This lets us double check the url we are about to take up
+ // if we choose to send the request to the url directly
+ //
+ if (req.url !== '/' && requestBody.url !== req.url) {
+ res.writeHead(400);
+ res.end('Requested url and actual url do not match');
+ return;
+ }
+
+ //
+ // Validate the schema
+ //
+ var validation = revalidator.validate(requestBody, schema);
+ if (!validation.valid) {
+ res.writeHead(400);
+ res.end(validation.errors.join('\n'));
+ return;
+ }
+
+ //
+ // Grab the current value from storage and
+ // check if it is a valid state for REST
+ //
+ var storedValue = memoryStore[requestBody.url];
+ if (req.method === 'POST') {
+ if (storedValue) {
+ res.writeHead(400);
+ res.end('ALREADY EXISTS');
+ return;
+ }
+ }
+ else if (!storedValue) {
+ res.writeHead(404);
+ res.end('DOES NOT EXIST');
+ return;
+ }
+
+ //
+ // Check our challenge
+ //
+ if (storedValue && requestBody.challenge != storedValue.challenge) {
+ res.writeHead(403);
+ res.end('NOT AUTHORIZED');
+ return;
+ }
+
+ //
+ // Since revalidator only checks and does not manipulate
+ // our object we need to set up the defaults our selves
+ // For an easier solution to this please look at Flatiron's
+ // `Resourceful` project
+ //
+ if (requestBody.body === undefined) {
+ requestBody.body = schema.properties.body.default;
+ }
+
+ //
+ // Use REST to determine how to manipulate the stored
+ // values
+ //
+ switch (req.method) {
+
+ case "GET":
+ res.writeHead(200);
+ var result = storedValue.body;
+ res.end(JSON.stringify(result));
+ return;
+
+ case "POST":
+ res.writeHead(201);
+ res.end();
+ memoryStore[requestBody.url] = requestBody;
+ return;
+
+ case "DELETE":
+ delete memoryStore[requestBody.url];
+ res.writeHead(200);
+ res.end();
+ return;
+
+ case "PUT":
+ memoryStore[requestBody.url] = requestBody;
+ res.writeHead(200);
+ res.end();
+ return;
+
+ default:
+ res.writeHead(400);
+ res.end('Invalid Http Verb');
+ return;
+ }
+ });
+})
+//
+// Listen to various ports depending on environment we are being run on
+//
+server.listen(process.env.PORT || process.env.C9_PORT || 1337, function reportListening () {
+
+ console.log('JSON REST Service listening on port', this.address().port);
+ console.log('Requests can be sent via REST to "/" if they conform to the following schema:');
+ console.log(JSON.stringify(schema, null, ' '));
+
+}); \ No newline at end of file
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);
diff --git a/node_modules/revalidator/package.json b/node_modules/revalidator/package.json
new file mode 100644
index 0000000..ee318b9
--- /dev/null
+++ b/node_modules/revalidator/package.json
@@ -0,0 +1,63 @@
+{
+ "_from": "revalidator@0.1.x",
+ "_id": "revalidator@0.1.8",
+ "_inBundle": false,
+ "_integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=",
+ "_location": "/revalidator",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "range",
+ "registry": true,
+ "raw": "revalidator@0.1.x",
+ "name": "revalidator",
+ "escapedName": "revalidator",
+ "rawSpec": "0.1.x",
+ "saveSpec": null,
+ "fetchSpec": "0.1.x"
+ },
+ "_requiredBy": [
+ "/prompt"
+ ],
+ "_resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
+ "_shasum": "fece61bfa0c1b52a206bd6b18198184bdd523a3b",
+ "_spec": "revalidator@0.1.x",
+ "_where": "/data/dev/Projets/Bingoloto Remote/node_modules/prompt",
+ "author": {
+ "name": "Nodejitsu Inc.",
+ "email": "info@nodejitsu.com"
+ },
+ "bugs": {
+ "url": "https://github.com/flatiron/revalidator/issues"
+ },
+ "bundleDependencies": false,
+ "deprecated": false,
+ "description": "A cross-browser / node.js validator used by resourceful",
+ "devDependencies": {
+ "vows": "0.7.0"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ },
+ "homepage": "https://github.com/flatiron/revalidator#readme",
+ "license": "Apache 2.0",
+ "main": "./lib/revalidator",
+ "maintainers": [
+ {
+ "name": "indexzero",
+ "email": "charlie@nodejitsu.com"
+ },
+ {
+ "name": "indutny",
+ "email": "fedor.indutny@gmail.com"
+ }
+ ],
+ "name": "revalidator",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://git@github.com/flatiron/revalidator.git"
+ },
+ "scripts": {
+ "test": "vows test/*-test.js --spec"
+ },
+ "version": "0.1.8"
+}
diff --git a/node_modules/revalidator/test/validator-test.js b/node_modules/revalidator/test/validator-test.js
new file mode 100644
index 0000000..6d962c2
--- /dev/null
+++ b/node_modules/revalidator/test/validator-test.js
@@ -0,0 +1,421 @@
+var assert = require('assert'),
+ vows = require('vows'),
+ revalidator = require('../lib/revalidator');
+
+function clone(object) {
+ return Object.keys(object).reduce(function (obj, k) {
+ obj[k] = object[k];
+ return obj;
+ }, {});
+};
+
+
+function assertInvalid(res) {
+ assert.isObject(res);
+ assert.strictEqual(res.valid, false);
+}
+
+function assertValid(res) {
+ assert.isObject(res);
+ assert.strictEqual(res.valid, true);
+}
+
+function assertHasError(attr, field) {
+ return function (res) {
+ assert.notEqual(res.errors.length, 0);
+ assert.ok(res.errors.some(function (e) {
+ return e.attribute === attr && (field ? e.property === field : true);
+ }));
+ };
+}
+
+function assertHasErrorMsg(attr, msg) {
+ return function (res) {
+ assert.notEqual(res.errors.length, 0);
+ assert.ok(res.errors.some(function (e) {
+ return e.attribute === attr && e.message === msg;
+ }));
+ };
+}
+
+function assertValidates(passingValue, failingValue, attributes) {
+ var schema = {
+ name: 'Resource',
+ properties: { field: {} }
+ };
+
+ var failing;
+
+ if (!attributes) {
+ attributes = failingValue;
+ failing = false;
+ } else {
+ failing = true;
+ }
+
+ var attr = Object.keys(attributes)[0];
+ revalidator.mixin(schema.properties.field, attributes);
+
+ var result = {
+ "when the object conforms": {
+ topic: function () {
+ return revalidator.validate({ field: passingValue }, schema);
+ },
+ "return an object with `valid` set to true": assertValid
+ }
+ };
+
+ if (failing) {
+ result["when the object does not conform"] ={
+ topic: function () {
+ return revalidator.validate({ field: failingValue }, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and an error concerning the attribute": assertHasError(Object.keys(attributes)[0], 'field')
+ };
+ };
+
+ return result;
+}
+
+vows.describe('revalidator', {
+ "Validating": {
+ "with <type>:'string'": assertValidates ('hello', 42, { type: "string" }),
+ "with <type>:'number'": assertValidates (42, 'hello', { type: "number" }),
+ "with <type>:'integer'": assertValidates (42, 42.5, { type: "integer" }),
+ "with <type>:'array'": assertValidates ([4, 2], 'hi', { type: "array" }),
+ "with <type>:'object'": assertValidates ({}, [], { type: "object" }),
+ "with <type>:'boolean'": assertValidates (false, 42, { type: "boolean" }),
+ "with <types>:bool,num": assertValidates (false, 'hello', { type: ["boolean", "number"] }),
+ "with <types>:bool,num": assertValidates (544, null, { type: ["boolean", "number"] }),
+ "with <type>:'null'": assertValidates (null, false, { type: "null" }),
+ "with <type>:'any'": assertValidates (9, { type: "any" }),
+ "with <type>:'date'": assertValidates (new Date(), 'hello', { type: "date" }),
+ "with <pattern>": assertValidates ("kaboom", "42", { pattern: /^[a-z]+$/ }),
+ "with <maxLength>": assertValidates ("boom", "kaboom", { maxLength: 4 }),
+ "with <minLength>": assertValidates ("kaboom", "boom", { minLength: 6 }),
+ "with <allowEmpty>": assertValidates ("hello", "", { allowEmpty: false }),
+ "with <minimum>": assertValidates ( 512, 43, { minimum: 473 }),
+ "with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }),
+ "with <divisibleBy>": assertValidates ( 10, 9, { divisibleBy: 5 }),
+ "with <divisibleBy> decimal": assertValidates ( 0.2, 0.009, { divisibleBy: 0.01 }),
+ "with <enum>": assertValidates ("orange", "cigar", { enum: ["orange", "apple", "pear"] }),
+ "with <format>:'url'": assertValidates ('http://test.com/', 'hello', { format: 'url' }),
+ "with <dependencies>": {
+ topic: {
+ properties: {
+ town: { dependencies: "country" },
+ country: { }
+ }
+ },
+ "when the object conforms": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", country: "moon" }, schema);
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "when the object does not conform": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna" }, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and an error concerning the attribute": assertHasError('dependencies')
+ }
+ },
+ "with <dependencies> as array": {
+ topic: {
+ properties: {
+ town: { dependencies: ["country", "planet"] },
+ country: { },
+ planet: { }
+ }
+ },
+ "when the object conforms": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", country: "moon", planet: "mars" }, schema);
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "when the object does not conform": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", planet: "mars" }, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and an error concerning the attribute": assertHasError('dependencies')
+ }
+ },
+ "with <dependencies> as schema": {
+ topic: {
+ properties: {
+ town: {
+ type: 'string',
+ dependencies: {
+ properties: { x: { type: "number" } }
+ }
+ },
+ country: { }
+ }
+ },
+ "when the object conforms": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", x: 1 }, schema);
+ },
+ "return an object with `valid` set to true": assertValid,
+ },
+ "when the object does not conform": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", x: 'no' }, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ }
+ },
+ "with <type>:'integer' and": {
+ "<minimum> constraints": assertValidates ( 512, 43, { minimum: 473, type: 'integer' }),
+ "<maximum> constraints": assertValidates ( 512, 1949, { maximum: 678, type: 'integer' }),
+ "<divisibleBy> constraints": assertValidates ( 10, 9, { divisibleBy: 5, type: 'integer' })
+ },
+ "with <additionalProperties>:false": {
+ topic: {
+ properties: {
+ town: { type: 'string' }
+ },
+ additionalProperties: false
+ },
+ "when the object conforms": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna" }, schema);
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "when the object does not conform": {
+ topic: function (schema) {
+ return revalidator.validate({ town: "luna", area: 'park' }, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ }
+ }
+ }
+}).addBatch({
+ "A schema": {
+ topic: {
+ name: 'Article',
+ properties: {
+ title: {
+ type: 'string',
+ maxLength: 140,
+ conditions: {
+ optional: function () {
+ return !this.published;
+ }
+ }
+ },
+ date: { type: 'string', format: 'date', messages: { format: "must be a valid %{expected} and nothing else" } },
+ body: { type: 'string' },
+ tags: {
+ type: 'array',
+ uniqueItems: true,
+ minItems: 2,
+ items: {
+ type: 'string',
+ pattern: /[a-z ]+/
+ }
+ },
+ tuple: {
+ type: 'array',
+ minItems: 2,
+ maxItems: 2,
+ items: {
+ type: ['string', 'number']
+ }
+ },
+ author: { type: 'string', pattern: /^[\w ]+$/i, required: true, messages: { required: "is essential for survival" } },
+ published: { type: 'boolean', 'default': false },
+ category: { type: 'string' },
+ palindrome: {type: 'string', conform: function(val) {
+ return val == val.split("").reverse().join(""); }
+ },
+ name: { type: 'string', default: '', conform: function(val, data) {
+ return (val === data.author); }
+ }
+ },
+ patternProperties: {
+ '^_': {
+ type: 'boolean', default: false
+ }
+ }
+ },
+ "and an object": {
+ topic: {
+ title: 'Gimme some Gurus',
+ date: '2012-02-04',
+ body: "And I will pwn your codex.",
+ tags: ['energy drinks', 'code'],
+ tuple: ['string0', 103],
+ author: 'cloudhead',
+ published: true,
+ category: 'misc',
+ palindrome: 'dennis sinned',
+ name: 'cloudhead',
+ _flag: true
+ },
+ "can be validated with `revalidator.validate`": {
+ "and if it conforms": {
+ topic: function (object, schema) {
+ return revalidator.validate(object, schema);
+ },
+ "return an object with the `valid` property set to true": assertValid,
+ "return an object with the `errors` property as an empty array": function (res) {
+ assert.isArray(res.errors);
+ assert.isEmpty(res.errors);
+ }
+ },
+ "and if it has a missing required property": {
+ topic: function (object, schema) {
+ object = clone(object);
+ delete object.author;
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and an error concerning the 'required' attribute": assertHasError('required'),
+ "and the error message defined": assertHasErrorMsg('required', "is essential for survival")
+ },
+ "and if it has a missing non-required property": {
+ topic: function (object, schema) {
+ object = clone(object);
+ delete object.category;
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertValid
+ },
+ "and if it has a incorrect pattern property": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object._additionalFlag = 'text';
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "and if it has a incorrect unique array property": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.tags = ['a', 'a'];
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "and if it has a incorrect array property (wrong values)": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.tags = ['a', '____'];
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "and if it has a incorrect array property (< minItems)": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.tags = ['x'];
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "and if it has a incorrect format (date)": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.date = 'bad date';
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and the error message defined": assertHasErrorMsg('format', "must be a valid date and nothing else")
+ },
+ "and if it is not a palindrome (conform function)": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.palindrome = 'bad palindrome';
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "and if it didn't validate a pattern": {
+ topic: function (object, schema) {
+ object = clone(object);
+ object.author = 'email@address.com';
+ return revalidator.validate(object, schema);
+ },
+ "return an object with `valid` set to false": assertInvalid,
+ "and an error concerning the 'pattern' attribute": assertHasError('pattern')
+ },
+ }
+ },
+ "with <cast> option": {
+ topic: {
+ properties: {
+ answer: { type: "integer" },
+ is_ready: { type: "boolean" }
+ }
+ },
+ "and <integer> property": {
+ "is castable string": {
+ topic: function (schema) {
+ return revalidator.validate({ answer: "42" }, schema, { cast: true });
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "is uncastable string": {
+ topic: function (schema) {
+ return revalidator.validate({ answer: "forty2" }, schema, { cast: true });
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "is casted to integer": {
+ topic: function (schema) {
+ var object = { answer: "42" };
+ revalidator.validate(object, schema, { cast: true });
+ return object;
+ },
+ "return an object with `answer` set to 42": function(res) { assert.strictEqual(res.answer, 42) }
+ }
+ },
+ "and <boolean> property": {
+ "is castable 'true/false' string": {
+ topic: function (schema) {
+ return revalidator.validate({ is_ready: "true" }, schema, { cast: true });
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "is castable '1/0' string": {
+ topic: function (schema) {
+ return revalidator.validate({ is_ready: "1" }, schema, { cast: true });
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "is castable `1/0` integer": {
+ topic: function (schema) {
+ return revalidator.validate({ is_ready: 1 }, schema, { cast: true });
+ },
+ "return an object with `valid` set to true": assertValid
+ },
+ "is uncastable string": {
+ topic: function (schema) {
+ return revalidator.validate({ is_ready: "not yet" }, schema, { cast: true });
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "is uncastable number": {
+ topic: function (schema) {
+ return revalidator.validate({ is_ready: 42 }, schema, { cast: true });
+ },
+ "return an object with `valid` set to false": assertInvalid
+ },
+ "is casted to boolean": {
+ topic: function (schema) {
+ var object = { is_ready: "true" };
+ revalidator.validate(object, schema, { cast: true });
+ return object;
+ },
+ "return an object with `is_ready` set to true": function(res) { assert.strictEqual(res.is_ready, true) }
+ }
+ }
+ }
+ }
+}).export(module);