Comparing version 2.7.0 to 2.8.0
{ | ||
"any": { | ||
"unknown": "the key {{key}} is not allowed", | ||
"without": "the value of {{key}} must exist without {{value}}", | ||
"invalid": "the value of {{key}} is not allowed to be {{value}}", | ||
@@ -35,3 +34,4 @@ "empty": "the value of {{key}} is not allowed to be empty", | ||
"base": "the value of {{key}} must be an array", | ||
"includes": "the value {{value}} in {{key}} does not match any of the allowed types", | ||
"includes": "the {{key}} array value in position {{pos}} does not match any of the allowed types", | ||
"includes-single": "the {{key}} array value in position {{pos}} fails because {{reason}}", | ||
"excludes": "the value {{value}} in {{key}} cannot violates exclusion rule {{pos}}", | ||
@@ -38,0 +38,0 @@ "min": "the length of {{key}} must include at least {{value}} items", |
@@ -23,2 +23,3 @@ // Load modules | ||
language: {}, | ||
languagePath: Path.join(__dirname, '..', 'languages', 'en-us.json') | ||
@@ -48,2 +49,8 @@ }; | ||
internals.Any.create = function () { | ||
return new internals.Any(); | ||
}; | ||
internals.Any.prototype._base = function (func) { | ||
@@ -73,10 +80,2 @@ | ||
internals.Any.error = function (type, context, options) { | ||
context = context || {}; | ||
context.key = options.key || '<root>'; | ||
return { type: type, context: context, path: options.path }; | ||
}; | ||
internals.Any.prototype.options = function (options) { | ||
@@ -175,3 +174,3 @@ | ||
if (!state.parent) { | ||
return internals.Any.error('any.with.parent', null, state); | ||
return Errors.create('any.with.parent', null, state, options); | ||
} | ||
@@ -187,3 +186,3 @@ | ||
state.parent[peer] === undefined) { | ||
return internals.Any.error('any.with.peer', { value: peer }, state); | ||
return Errors.create('any.with.peer', { value: peer }, state, options); | ||
} | ||
@@ -209,3 +208,3 @@ } | ||
if (!state.parent) { | ||
return internals.Any.error('any.without.parent', null, state); | ||
return Errors.create('any.without.parent', null, state, options); | ||
} | ||
@@ -222,3 +221,3 @@ | ||
return internals.Any.error('any.without.peer', { value: peer }, state); | ||
return Errors.create('any.without.peer', { value: peer }, state, options); | ||
} | ||
@@ -241,3 +240,3 @@ } | ||
if (!state.parent) { | ||
return internals.Any.error('any.xor.parent', null, state); | ||
return Errors.create('any.xor.parent', null, state, options); | ||
} | ||
@@ -261,6 +260,6 @@ | ||
if (present === 0) { | ||
return (present === 1 ? null : internals.Any.error('any.xor.missing', { value: peers }, state)); | ||
return Errors.create('any.xor.missing', { value: peers }, state, options); | ||
} | ||
return internals.Any.error('any.xor.peer', { value: peers }, state); | ||
return Errors.create('any.xor.peer', { value: peers }, state, options); | ||
}); | ||
@@ -282,3 +281,3 @@ | ||
if (!state.parent) { | ||
return internals.Any.error('any.or.parent', null, state); | ||
return Errors.create('any.or.parent', null, state, options); | ||
} | ||
@@ -298,3 +297,3 @@ | ||
return internals.Any.error('any.or.peer', { value: peers }, state); | ||
return Errors.create('any.or.peer', { value: peers }, state, options); | ||
}); | ||
@@ -319,3 +318,3 @@ | ||
if (!state.parent) { | ||
return internals.Any.error('any.rename.parent', null, state); | ||
return Errors.create('any.rename.parent', null, state, options); | ||
} | ||
@@ -326,3 +325,3 @@ | ||
return internals.Any.error('any.rename.multiple', { value: to }, state); | ||
return Errors.create('any.rename.multiple', { value: to }, state, options); | ||
} | ||
@@ -334,3 +333,3 @@ | ||
return internals.Any.error('any.rename.override', { value: to }, state); | ||
return Errors.create('any.rename.override', { value: to }, state, options); | ||
} | ||
@@ -352,2 +351,9 @@ | ||
internals.Any.prototype.default = function (value) { | ||
this._flags.default = value; | ||
return this; | ||
}; | ||
internals.Any.prototype.description = function (desc) { | ||
@@ -412,3 +418,3 @@ | ||
if (self._invalids.has(value, self._flags.insensitive)) { | ||
errors.push(internals.Any.error(value === '' ? 'any.empty' : 'any.invalid', { value: (value === '' ? '' : self._invalids.key(value)) }, state)); | ||
errors.push(Errors.create(value === '' ? 'any.empty' : 'any.invalid', { value: (value === '' ? '' : self._invalids.key(value)) }, state, options)); | ||
if (options.abortEarly) { | ||
@@ -435,3 +441,3 @@ return errors; | ||
if (self._invalids.has(value, self._flags.insensitive)) { | ||
errors.push(internals.Any.error(value === '' ? 'any.empty' : 'any.invalid', { value: (value === '' ? '' : self._invalids.key(value)) }, state)); | ||
errors.push(Errors.create('any.invalid', { value: self._invalids.key(value) }, state, options)); | ||
if (options.abortEarly) { | ||
@@ -447,3 +453,3 @@ return errors; | ||
if (self._flags.allowOnly) { | ||
errors.push(internals.Any.error('any.validate.allowOnly', { value: self._valids.toString(false) }, state)); | ||
errors.push(Errors.create('any.validate.allowOnly', { value: self._valids.toString(false) }, state, options)); | ||
if (options.abortEarly) { | ||
@@ -488,5 +494,5 @@ return errors; | ||
state.parent && | ||
options.modify) { | ||
((options.modify && state.parent.hasOwnProperty(state.key)) || (value === undefined && self._flags.default !== undefined))) { | ||
state.parent[state.key] = value; | ||
state.parent[state.key] = (value !== undefined ? value : self._flags.default); | ||
} | ||
@@ -510,3 +516,3 @@ | ||
var errors = this._validate(object, null, settings); | ||
return Errors.process(errors, object, settings); | ||
return Errors.process(errors, object); | ||
}; | ||
@@ -513,0 +519,0 @@ |
@@ -5,2 +5,3 @@ // Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -30,3 +31,3 @@ | ||
return Any.error('array.base', { value: value }, state); | ||
return Errors.create('array.base', { value: value }, state, options); | ||
}); | ||
@@ -38,2 +39,8 @@ }; | ||
internals.Array.create = function () { | ||
return new internals.Array(); | ||
}; | ||
internals.Array.prototype._convert = function (value) { | ||
@@ -74,3 +81,3 @@ | ||
for (var i = 0, il = inclusions.length; i < il; ++i) { | ||
var err = inclusions[i].validate(item, options); | ||
var err = inclusions[i]._validate(item, { parent: value, key: v, path: (state.path ? state.path + '.' : '') + v, renamed: state.renamed }, options); | ||
if (!err) { | ||
@@ -80,6 +87,12 @@ isValid = true; | ||
} | ||
// Return the actual error if only one inclusion defined | ||
if (il === 1) { | ||
return Errors.create('array.includes-single', { value: item, pos: v, reason: err }, state, options); | ||
} | ||
} | ||
if (!isValid) { | ||
return Any.error('array.includes', { value: item }, state); | ||
return Errors.create('array.includes', { value: item, pos: v }, state, options); | ||
} | ||
@@ -106,3 +119,3 @@ } | ||
if (!err) { | ||
return Any.error('array.excludes', { value: item, pos: i + 1 }, state); | ||
return Errors.create('array.excludes', { value: item, pos: i + 1 }, state, options); | ||
} | ||
@@ -129,3 +142,3 @@ } | ||
return Any.error('array.min', { value: limit }, state); | ||
return Errors.create('array.min', { value: limit }, state, options); | ||
}); | ||
@@ -147,3 +160,3 @@ | ||
return Any.error('array.max', { value: limit }, state); | ||
return Errors.create('array.max', { value: limit }, state, options); | ||
}); | ||
@@ -165,3 +178,3 @@ | ||
return Any.error('array.length', { value: limit }, state); | ||
return Errors.create('array.length', { value: limit }, state, options); | ||
}); | ||
@@ -168,0 +181,0 @@ |
// Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -23,3 +24,3 @@ | ||
return Any.error('boolean.base', null, state); | ||
return Errors.create('boolean.base', null, state, options); | ||
}); | ||
@@ -31,2 +32,8 @@ }; | ||
internals.Boolean.create = function () { | ||
return new internals.Boolean(); | ||
}; | ||
internals.Boolean.prototype._convert = function (value) { | ||
@@ -33,0 +40,0 @@ |
// Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -23,3 +24,3 @@ | ||
return Any.error('date.base', { value: value }, state); | ||
return Errors.create('date.base', { value: value }, state, options); | ||
}); | ||
@@ -31,2 +32,8 @@ }; | ||
internals.Date.create = function () { | ||
return new internals.Date(); | ||
}; | ||
internals.toDate = function (value) { | ||
@@ -65,3 +72,3 @@ | ||
return Any.error('date.min', { value: date }, state); | ||
return Errors.create('date.min', { value: date }, state, options); | ||
}); | ||
@@ -84,3 +91,3 @@ | ||
return Any.error('date.max', { value: date }, state); | ||
return Errors.create('date.max', { value: date }, state, options); | ||
}); | ||
@@ -87,0 +94,0 @@ |
@@ -11,4 +11,39 @@ // Load modules | ||
exports.process = function (errors, object, options) { | ||
internals.Err = function (type, context, state, options) { | ||
this.type = type; | ||
this.context = context || {}; | ||
this.context.key = state.key || '<root>'; | ||
this.path = state.path; | ||
this.options = options; | ||
}; | ||
internals.Err.prototype.toString = function () { | ||
var self = this; | ||
var localized = this.options.language || {}; | ||
var language = require(this.options.languagePath); | ||
var format = Utils.reach(localized, this.type) || Utils.reach(language, this.type); | ||
if (!format) { | ||
return this.context.key; | ||
} | ||
return format.replace(/\{\{\s*([^\s}]+?)\s*\}\}/ig, function (match, name) { | ||
return Utils.reach(self.context, name).toString(); | ||
}); | ||
}; | ||
exports.create = function (type, context, state, options) { | ||
return new internals.Err(type, context, state, options); | ||
}; | ||
exports.process = function (errors, object) { | ||
if (!errors || !errors.length) { | ||
@@ -18,16 +53,6 @@ return null; | ||
var resources = require(options.languagePath); | ||
var details = []; | ||
for (var i = 0, il = errors.length; i < il; ++i) { | ||
var item = errors[i]; | ||
var message = Utils.reach(resources, item.type); | ||
if (message) { | ||
message = message.replace(/\{\{\s*([^\s}]+?)\s*\}\}/ig, function (match, name) { return Utils.reach(item.context, name); }); | ||
} | ||
else { | ||
message = item.context.key; | ||
} | ||
details.push({ message: message, path: item.path || item.context.key, type: item.type }); | ||
details.push({ message: item.toString(), path: item.path || item.context.key, type: item.type }); | ||
} | ||
@@ -34,0 +59,0 @@ |
// Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -23,3 +24,3 @@ | ||
return Any.error('function.base', null, state); | ||
return Errors.create('function.base', null, state, options); | ||
}); | ||
@@ -29,1 +30,7 @@ }; | ||
Utils.inherits(internals.Function, Any); | ||
internals.Function.create = function () { | ||
return new internals.Function(); | ||
}; |
@@ -5,2 +5,3 @@ // Load modules | ||
var Any = require('./any'); | ||
var Cast = require('./cast'); | ||
@@ -13,22 +14,16 @@ | ||
internals.create = function (Type) { | ||
exports.any = Any.create; | ||
exports.alternatives = exports.alt = require('./alternatives').create; | ||
exports.array = require('./array').create; | ||
exports.boolean = exports.bool = require('./boolean').create; | ||
exports.date = require('./date').create; | ||
exports.func = require('./function').create; | ||
exports.number = require('./number').create; | ||
exports.object = require('./object').create; | ||
exports.string = require('./string').create; | ||
return function (arg) { | ||
return new Type(arg); | ||
}; | ||
}; | ||
exports.any = internals.create(Any); | ||
exports.array = internals.create(require('./array')); | ||
exports.boolean = exports.bool = internals.create(require('./boolean')); | ||
exports.date = internals.create(require('./date')); | ||
exports.func = internals.create(require('./function')); | ||
exports.number = internals.create(require('./number')); | ||
exports.object = internals.create(require('./object')); | ||
exports.string = internals.create(require('./string')); | ||
exports.types = exports.Types = { | ||
any: exports.any, | ||
alternatives: exports.alternatives, | ||
array: exports.array, | ||
@@ -58,9 +53,3 @@ boolean: exports.boolean, | ||
Utils.assert(typeof schema === 'object', 'Schema must be an object'); | ||
if (typeof schema.validate === 'function') { | ||
return schema.validate(object, options); | ||
} | ||
return exports.object(schema).validate(object, options); | ||
return Cast.schema(schema).validate(object, options); | ||
}; | ||
@@ -67,0 +56,0 @@ |
// Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -23,3 +24,3 @@ | ||
return Any.error('number.base', { value: value }, state); | ||
return Errors.create('number.base', { value: value }, state, options); | ||
}); | ||
@@ -31,2 +32,8 @@ }; | ||
internals.Number.create = function () { | ||
return new internals.Number(); | ||
}; | ||
internals.Number.prototype._convert = function (value) { | ||
@@ -56,3 +63,3 @@ if (typeof value === 'string') { | ||
return Any.error('number.min', { value: limit }, state); | ||
return Errors.create('number.min', { value: limit }, state, options); | ||
}); | ||
@@ -74,3 +81,3 @@ | ||
return Any.error('number.max', { value: limit }, state); | ||
return Errors.create('number.max', { value: limit }, state, options); | ||
}); | ||
@@ -90,3 +97,3 @@ | ||
return Any.error('number.int', { value: value }, state); | ||
return Errors.create('number.int', { value: value }, state, options); | ||
}); | ||
@@ -106,3 +113,3 @@ | ||
return Any.error('number.negative', { value: value }, state); | ||
return Errors.create('number.negative', { value: value }, state, options); | ||
}); | ||
@@ -122,3 +129,3 @@ | ||
return Any.error('number.positive', { value: value }, state); | ||
return Errors.create('number.positive', { value: value }, state, options); | ||
}); | ||
@@ -125,0 +132,0 @@ |
// Load modules | ||
var Any = require('./any'); | ||
var Cast = require('./cast'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -25,3 +27,3 @@ | ||
return Any.error('object.base', null, state); | ||
return Errors.create('object.base', null, state, options); | ||
} | ||
@@ -36,2 +38,8 @@ | ||
internals.Object.create = function (schema) { | ||
return new internals.Object(schema); | ||
}; | ||
internals.Object.prototype._convert = function (value) { | ||
@@ -65,14 +73,3 @@ | ||
var child = this._children[key]; | ||
var configs = Array.isArray(child) ? child : [child]; | ||
for (var n = 0, nl = configs.length; n < nl; ++n) { | ||
var config = (typeof configs[n].describe === 'function' ? configs[n] : new internals.Object(configs[n])); | ||
if (nl > 1) { | ||
description.children[key] = description.children[key] || []; | ||
description.children[key].push(config.describe()); | ||
} | ||
else { | ||
description.children[key] = config.describe(); | ||
} | ||
} | ||
description.children[key] = Cast.schema(child).describe(); | ||
} | ||
@@ -98,3 +95,3 @@ } | ||
return Any.error('object.length', { value: limit }, state); | ||
return Errors.create('object.length', { value: limit }, state, options); | ||
}); | ||
@@ -119,3 +116,3 @@ | ||
return Any.error('object.min', { value: limit }, state); | ||
return Errors.create('object.min', { value: limit }, state, options); | ||
}); | ||
@@ -140,3 +137,3 @@ | ||
return Any.error('object.max', { value: limit }, state); | ||
return Errors.create('object.max', { value: limit }, state, options); | ||
}); | ||
@@ -164,18 +161,6 @@ | ||
var configs = Array.isArray(child) ? child : [child]; | ||
var itemErrors = []; | ||
for (var c = 0, cl = configs.length; c < cl; ++c) { | ||
var config = (typeof configs[c]._validate === 'function' ? configs[c] : new internals.Object(configs[c])); | ||
var err = config._validate(item, { parent: value, key: key, path: (state.path ? state.path + '.' : '') + key, renamed: state.renamed }, options); | ||
if (!err) { // Found a valid match | ||
itemErrors = []; | ||
break; | ||
} | ||
itemErrors = itemErrors.concat(err); | ||
} | ||
if (itemErrors.length) { | ||
errors = errors.concat(itemErrors); | ||
var localState = { parent: value, key: key, path: (state.path ? state.path + '.' : '') + key, renamed: state.renamed }; | ||
var err = Cast.schema(child)._validate(item, localState, options); | ||
if (err) { | ||
errors = errors.concat(err); | ||
if (options.abortEarly) { | ||
@@ -219,3 +204,3 @@ return errors; | ||
for (var e = 0, el = unprocessedKeys.length; e < el; ++e) { | ||
errors.push(Any.error('object.allowUnknown', null, { key: unprocessedKeys[e], path: state.path })); | ||
errors.push(Errors.create('object.allowUnknown', null, { key: unprocessedKeys[e], path: state.path }, options)); | ||
} | ||
@@ -222,0 +207,0 @@ } |
// Load modules | ||
var Any = require('./any'); | ||
var Errors = require('./errors'); | ||
var Utils = require('./utils'); | ||
@@ -27,3 +28,3 @@ | ||
return Any.error('string.base', null, state); | ||
return Errors.create('string.base', null, state, options); | ||
}); | ||
@@ -35,2 +36,8 @@ }; | ||
internals.String.create = function () { | ||
return new internals.String(); | ||
}; | ||
internals.String.prototype.emptyOk = function () { | ||
@@ -56,4 +63,3 @@ | ||
if (value !== null && | ||
value !== undefined && | ||
if (typeof value === 'string' && | ||
value.length >= limit) { | ||
@@ -64,3 +70,3 @@ | ||
return Any.error('string.min', { value: limit }, state); | ||
return Errors.create('string.min', { value: limit }, state, options); | ||
}); | ||
@@ -78,3 +84,3 @@ | ||
if (value !== null && | ||
if (!value || | ||
value.length <= limit) { | ||
@@ -85,3 +91,3 @@ | ||
return Any.error('string.max', { value: limit }, state); | ||
return Errors.create('string.max', { value: limit }, state, options); | ||
}); | ||
@@ -99,3 +105,3 @@ | ||
if (value !== null && | ||
if (typeof value === 'string' && | ||
value.length === limit) { | ||
@@ -106,3 +112,3 @@ | ||
return Any.error('string.length', { value: limit }, state); | ||
return Errors.create('string.length', { value: limit }, state, options); | ||
}); | ||
@@ -120,4 +126,3 @@ | ||
if (value !== undefined && | ||
value !== null && | ||
if (typeof value === 'string' && | ||
value.match(pattern)) { | ||
@@ -128,3 +133,3 @@ | ||
return Any.error('string.regex', { value: pattern.toString() }, state); | ||
return Errors.create('string.regex', { value: pattern.toString() }, state, options); | ||
}); | ||
@@ -140,4 +145,3 @@ | ||
if (value !== undefined && | ||
value !== null && | ||
if (typeof value === 'string' && | ||
value.match(/^[a-zA-Z0-9]+$/)) { | ||
@@ -148,3 +152,3 @@ | ||
return Any.error('string.alphanum', null, state); | ||
return Errors.create('string.alphanum', null, state, options); | ||
}); | ||
@@ -160,4 +164,3 @@ | ||
if (value !== undefined && | ||
value !== null && | ||
if (typeof value === 'string' && | ||
value.match(/^\w+$/)) { | ||
@@ -168,3 +171,3 @@ | ||
return Any.error('string.token', null, state); | ||
return Errors.create('string.token', null, state, options); | ||
}); | ||
@@ -182,9 +185,11 @@ | ||
if (value.match(regex)) { | ||
if (typeof value === 'string' && | ||
value.match(regex)) { | ||
return null; | ||
} | ||
return Any.error('string.email', null, state); | ||
return Errors.create('string.email', null, state, options); | ||
}); | ||
return this; | ||
@@ -200,7 +205,9 @@ }; | ||
if (value.match(regex)) { | ||
if (typeof value === 'string' && | ||
value.match(regex)) { | ||
return null; | ||
} | ||
return Any.error('string.isoDate', null, state); | ||
return Errors.create('string.isoDate', null, state, options); | ||
}); | ||
@@ -219,7 +226,9 @@ | ||
if (value.match(regex) || value.match(regex2)) { | ||
if (typeof value === 'string' && | ||
value.match(regex) || value.match(regex2)) { | ||
return null; | ||
} | ||
return Any.error('string.guid', null, state); | ||
return Errors.create('string.guid', null, state, options); | ||
}); | ||
@@ -226,0 +235,0 @@ |
{ | ||
"name": "joi", | ||
"description": "Object schema validation", | ||
"version": "2.7.0", | ||
"version": "2.8.0", | ||
"repository": "git://github.com/spumko/joi", | ||
@@ -12,3 +12,3 @@ "main": "index", | ||
"engines": { | ||
"node": "0.10.x" | ||
"node": ">=0.10.22" | ||
}, | ||
@@ -15,0 +15,0 @@ "dependencies": { |
@@ -6,3 +6,3 @@ <a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a> | ||
Current version: **2.4.x** | ||
Current version: **2.8.x** | ||
@@ -34,2 +34,3 @@ [![Build Status](https://secure.travis-ci.org/spumko/joi.png)](http://travis-ci.org/spumko/joi) | ||
- [`any.rename(to, [options])`](#anyrenameto-options) | ||
- [`any.default(value)`](#anydefault) | ||
- [`array()`](#array) | ||
@@ -60,2 +61,3 @@ - [`array.includes(type)`](#arrayincludestype) | ||
- [`string.email()`](#stringemail) | ||
- [`alternatives(types)`](#alternativestypes) | ||
- [Migration notes](#migration-notes) | ||
@@ -147,2 +149,4 @@ | ||
- `stripUnknown` - when `true`, unknown keys are deleted (only when value is an object). Defaults to `false`. | ||
- `language` - a localized langugage object using the format of the `languagePath` file. Error formats are looked up in the `language` | ||
object first, and then in the `languagePath` file. Defaults to no override (`{}`). | ||
- `languagePath` - the location of the language file used to localize error messages. Defaults to `'languages/en-us.json'`. | ||
@@ -347,2 +351,16 @@ | ||
#### `any.default(value)` | ||
Sets a default value if the original value is undefined where: | ||
- `value` - the value. | ||
```javascript | ||
var schema = { | ||
username: Joi.string().default('new_user') | ||
}; | ||
var input = {}; | ||
Joi.validate(input, schema); | ||
// input === { username: "new_user" } | ||
``` | ||
### `array()` | ||
@@ -542,3 +560,3 @@ | ||
var object = Joi.object({ | ||
a: number.min(1).max(10).integer() | ||
a: Joi.number.min(1).max(10).integer() | ||
}); | ||
@@ -666,2 +684,18 @@ | ||
### `alternatives(types)` | ||
Generates a type that will match one of the provided alternative schemas where: | ||
- `types` - an array of alternaitve **joi** types. Also supports providing each type as a separate argument. | ||
Supports the same methods of the [`any()`](#any) type. | ||
```javascript | ||
var alt = Joi.alternatives(Joi.number(), Joi.string()); | ||
var err = alt.validate('a'); | ||
``` | ||
Note that the `alternatives()` type does not behave the same way as passing multiple alternatives directly using an | ||
array of types (e.g. `{ a: [Joi.number(), Joi.string()] }`). When passing an array directly, the value must match one | ||
of the provided types while when using the `alternatives()` type, the key is optional by default. | ||
# Migration notes | ||
@@ -668,0 +702,0 @@ |
@@ -242,4 +242,47 @@ // Load modules | ||
}); | ||
it('renames when data is nested in an array via includes', function (done) { | ||
var schema = { | ||
arr: Joi.array().includes(Joi.object({ | ||
uno: Joi.string().rename('one'), | ||
dos: Joi.string().rename('two') | ||
})) | ||
}; | ||
var data = { arr: [{ uno: '1', dos: '2' }] }; | ||
var err = Joi.validate(data, schema); | ||
expect(err).to.not.exist; | ||
expect(data.arr[0].one).to.equal('1'); | ||
expect(data.arr[0].two).to.equal('2'); | ||
done(); | ||
}); | ||
}); | ||
describe('#default', function () { | ||
it('sets the value', function (done) { | ||
var schema = { foo: Joi.string().default('test') }; | ||
var input = {}; | ||
expect(Joi.validate(input, schema)).to.not.exist; | ||
expect(input.foo).to.equal('test'); | ||
done(); | ||
}); | ||
it('should not overide a value when value is given', function (done) { | ||
var schema = { foo: Joi.string().default('bar') }; | ||
var input = { foo: 'test' }; | ||
expect(Joi.validate(input, schema)).to.not.exist; | ||
expect(input.foo).to.equal('test'); | ||
done(); | ||
}); | ||
}); | ||
describe('#validateCallback', function () { | ||
@@ -294,4 +337,17 @@ | ||
}); | ||
describe('Set', function () { | ||
describe('#toString', function () { | ||
it('includes undefined', function (done) { | ||
var b = Joi.any(); | ||
expect(b._valids.toString(true)).to.equal('undefined'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -65,2 +65,43 @@ // Load modules | ||
describe('#includes', function () { | ||
it('converts members', function (done) { | ||
var array = ['1', '2', '3']; | ||
var schema = Joi.array().includes(Joi.number()); | ||
var err = Joi.validate(array, schema, { modify: true }); | ||
expect(err).to.not.exist; | ||
expect(array).to.deep.equal([1, 2, 3]); | ||
done(); | ||
}); | ||
it('allows zero size', function (done) { | ||
var data = { test: [] }; | ||
var schema = { | ||
test: Joi.array().includes(Joi.object({ | ||
foo: Joi.string().required() | ||
})) | ||
}; | ||
var err = Joi.validate(data, schema); | ||
expect(err).to.not.exist; | ||
done(); | ||
}); | ||
it('returns the first error when only one inclusion', function (done) { | ||
var data = { test: [{ foo: 'a' }, { bar: 2 }] }; | ||
var schema = { | ||
test: Joi.array().includes(Joi.object({ | ||
foo: Joi.string().required() | ||
})) | ||
}; | ||
var err = Joi.validate(data, schema); | ||
expect(err.message).to.equal('the test array value in position 1 fails because the value of foo is not allowed to be undefined'); | ||
done(); | ||
}); | ||
}); | ||
describe('#min', function () { | ||
@@ -209,3 +250,3 @@ | ||
expect(err).to.exist; | ||
expect(err.message).to.equal('the value 2.1 in arr does not match any of the allowed types'); | ||
expect(err.message).to.equal('the arr array value in position 2 fails because the value of 2 must be an integer'); | ||
done(); | ||
@@ -212,0 +253,0 @@ }); |
@@ -252,2 +252,4 @@ // Load modules | ||
[{ auth: null }, true], | ||
[{ auth: undefined }, true], | ||
[{}, true], | ||
[{ auth: true }, true], | ||
@@ -260,2 +262,30 @@ [{ auth: 123 }, false] | ||
it('validates alternatives', function (done) { | ||
var schema = { | ||
auth: Joi.alternatives( | ||
Joi.object({ mode: Joi.string().valid('required', 'optional', 'try').nullOk() }).nullOk(), | ||
Joi.string(), | ||
Joi.boolean() | ||
) | ||
}; | ||
var err = Joi.validate({ auth: { mode: 'none' } }, schema); | ||
expect(err).to.exist; | ||
expect(err.message).to.equal('the value of mode must be one of required, optional, try, null. the value of auth must be a string. the value of auth must be a boolean'); | ||
Validate(schema, [ | ||
[{ auth: { mode: 'try' } }, true], | ||
[{ something: undefined }, false], | ||
[{ auth: { something: undefined } }, false], | ||
[{ auth: null }, true], | ||
[{ auth: undefined }, true], | ||
[{}, true], | ||
[{ auth: true }, true], | ||
[{ auth: 123 }, false] | ||
]); | ||
done(); | ||
}); | ||
it('validates an array of string with valid', function (done) { | ||
@@ -298,2 +328,16 @@ | ||
it('does not set optional keys when missing', function (done) { | ||
var schema = { | ||
a: Joi.number() | ||
}; | ||
var obj = {}; | ||
var err = Joi.validate(obj, schema, { modify: true }); | ||
expect(err).to.not.exist; | ||
expect(obj.hasOwnProperty('a')).to.equal(false); | ||
done(); | ||
}); | ||
it('invalidates pre and post convert value', function (done) { | ||
@@ -446,3 +490,3 @@ | ||
var err = Joi.validate({}, config); | ||
expect(err).to.not.be.null; | ||
expect(err).to.exist; | ||
expect(err.message).to.contain('the value of module is not allowed to be undefined'); | ||
@@ -462,2 +506,37 @@ | ||
it('validates key with required alternatives', function (done) { | ||
var config = { | ||
module: Joi.alt( | ||
Joi.object({ | ||
compile: Joi.func().required(), | ||
execute: Joi.func() | ||
}).required(), | ||
Joi.string().required() | ||
) | ||
}; | ||
var err = Joi.validate({}, config); | ||
expect(err).to.not.exist; | ||
done(); | ||
}); | ||
it('validates required key with alternatives', function (done) { | ||
var config = { | ||
module: Joi.alt( | ||
Joi.object({ | ||
compile: Joi.func().required(), | ||
execute: Joi.func() | ||
}), | ||
Joi.string() | ||
).required() | ||
}; | ||
var err = Joi.validate({}, config); | ||
expect(err).to.exist; | ||
expect(err.message).to.contain('the value of module is not allowed to be undefined'); | ||
done(); | ||
}); | ||
it('does not require optional numbers', function (done) { | ||
@@ -921,2 +1000,44 @@ | ||
it('supports custom errors and localized errors when validating types', function (done) { | ||
var schema = { | ||
email: Joi.string().email(), | ||
date: Joi.date(), | ||
alphanum: Joi.string().alphanum(), | ||
min: Joi.string().min(3), | ||
max: Joi.string().max(3), | ||
required: Joi.string().required().without('xor'), | ||
xor: Joi.string().without('required'), | ||
renamed: Joi.string().rename('required').valid('456'), | ||
notEmpty: Joi.string().required() | ||
}; | ||
var input = { | ||
email: 'invalid-email', | ||
date: 'invalid-date', | ||
alphanum: '\b\n\f\r\t', | ||
min: 'ab', | ||
max: 'abcd', | ||
required: 'hello', | ||
xor: '123', | ||
renamed: '456', | ||
notEmpty: '' | ||
}; | ||
var options = { | ||
abortEarly: false, | ||
language: { | ||
any: { | ||
empty: 'Custome!' | ||
} | ||
}, | ||
languagePath: Path.join(__dirname, 'languages', 'en-us.json') | ||
}; | ||
var err = Joi.validate(input, schema, options); | ||
expect(err).to.exist; | ||
expect(err.message).to.equal('19. 18. 16. 14. 15. 7. 7. 11. Custome!'); | ||
done(); | ||
}); | ||
it('returns key when language file missing item', function (done) { | ||
@@ -923,0 +1044,0 @@ |
@@ -195,4 +195,29 @@ // Load modules | ||
}); | ||
it('should traverse an object several levels with required levels (without Joi.obj())', function (done) { | ||
var schema = { | ||
obj: { | ||
obj: { | ||
obj: { | ||
item: Joi.boolean().required() | ||
} | ||
} | ||
} | ||
}; | ||
Validate(schema, [ | ||
[null, false], | ||
[undefined, true], | ||
[{}, true], | ||
[{ obj: {} }, true], | ||
[{ obj: { obj: {} } }, true], | ||
[{ obj: { obj: { obj: {} } } }, false], | ||
[{ obj: { obj: { obj: { item: true } } } }, true], | ||
[{ obj: { obj: { obj: { item: 10 } } } }, false] | ||
]); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
351083
37
4693
726