Socket
Socket
Sign inDemoInstall

joi

Package Overview
Dependencies
Maintainers
3
Versions
238
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

joi - npm Package Compare versions

Comparing version 0.3.5 to 0.3.6

languages/en-US.json

28

lib/errors.js
// Load modules
var Messages = require('./messages');
var Utils = require('./utils');

@@ -11,6 +12,8 @@

module.exports = internals.Errors = function (object) {
module.exports = internals.Errors = function (object, config) {
this._object = object;
this._values = [];
config = config || {};
this._messages = new Messages({ languagePath: config.languagePath } );
};

@@ -21,13 +24,18 @@

var topPath = path.split('.')[0];
if (message && !this._values.some(function (error) { // Don't add an error when there is already a more specific one
this._values.push({
message: message,
path: path
});
};
return topPath === error.path.split('.')[0];
})) {
this._values.push({
message: message,
path: path
});
}
internals.Errors.prototype.addLocalized = function (type, key, value, path) {
var message = this._messages.print(type, key, value);
Utils.assert(message, 'No message resource found in languages');
this._values.push({
message: message,
path: path
});
};

@@ -34,0 +42,0 @@

@@ -29,3 +29,3 @@ // Load modules

var skipFunctions = this.settings.skipFunctions;
var errors = new Errors(object);
var errors = new Errors(object, config);

@@ -35,3 +35,3 @@ var processConfig = function () {

if (config instanceof Types.Base) {
return validateKeyConfig(config, '', object);
return validateKeyConfig(config, null, object);
}

@@ -63,13 +63,9 @@

var converted;
var errorFilter = function (error) {
return error.path !== key;
};
if (keyConfig instanceof Array) {
if (Array.isArray(keyConfig)) {
var localErrors = new Errors(object, config);
for (var i = 0, il = keyConfig.length; i < il; ++i) {
converted = convertType(keyConfig[i], key, value);
if (converted && keyConfig[i].validate(converted.value, object, key, errors, key)) {
errors._values = errors._values.filter(errorFilter);
if (converted && keyConfig[i].validate(converted.value, object, key, localErrors, key)) {
return true;

@@ -79,2 +75,7 @@ }

localErrors._values.map(function(error) {
errors.add(error.message, error.path);
});
return false;

@@ -93,16 +94,11 @@ }

if (!self.settings.skipConversions && typeof converter === 'function') {
try {
value = converter(value);
if (self.settings.saveConversions) {
object[key] = value;
}
value = converter(value);
if (self.settings.saveConversions && key !== null) {
object[key] = value;
}
return { value: value };
}
catch (err) {
return;
}
return { value: value };
}
return { value: value }; // If no convert function then just return the value
return { value: value }; // If no convert function then just return the value
};

@@ -113,2 +109,2 @@

return errors.toError();
};
};

@@ -20,3 +20,3 @@ // Load modules

Utils.assert(initialValue instanceof Array, 'Improper initial value provided');
Utils.assert(Array.isArray(initialValue), 'Improper initial value provided');

@@ -81,2 +81,2 @@ for (var i = initialValue.length - 1; i >= 0; i--) {

return this._values.map(fn);
};
};

@@ -44,6 +44,5 @@ // Load modules

// No need to try/catch, `Invalid JSON Body` exception already handled elsehwere
try {
var converted = JSON.parse(value);
if (converted instanceof Array) {
if (Array.isArray(converted)) {
return converted;

@@ -57,4 +56,3 @@ }

//JSON.parse failed, means that given string is a string
//which cannot be converted into JSON format. Just return it as an array.
return [value];
return value;
}

@@ -74,5 +72,5 @@ }

var result = value instanceof Array;
var result = Array.isArray(value);
if (!result) {
errors.add('the value of ' + key + ' must be an Array', keyPath);
errors.addLocalized('array.base', key, value, keyPath);
}

@@ -79,0 +77,0 @@

// Load modules
var Errors = require('../errors');
var Utils = require('../utils');

@@ -206,2 +207,5 @@ var Set = require('../set');

for (var i = 0, li = arguments.length; i < li; i++) {
Utils.assert(typeof arguments[i] === 'string', 'arguments must be a string')
}
this.add('with', this._with(Array.prototype.slice.call(arguments)), arguments);

@@ -225,2 +229,5 @@ return this;

for (var i = 0, li = arguments.length; i < li; i++) {
Utils.assert(typeof arguments[i] === 'string', 'arguments must be a string')
}
if (this.__modifiers.has('required')) {

@@ -324,5 +331,12 @@ return this.xor(Array.prototype.slice.call(arguments));

internals.BaseType.prototype.noShortCircuit = function () {
this.options.shortCircuit = false;
return this;
};
internals.BaseType.prototype.notes = function (notes) {
Utils.assert(typeof notes === 'string' || notes instanceof Array, 'Validator notes must be a string or array');
Utils.assert(typeof notes === 'string' || Array.isArray(notes), 'Validator notes must be a string or array');
this.notes = notes || '';

@@ -335,3 +349,3 @@ return this;

Utils.assert(tags instanceof Array, 'Validator tags must be an array');
Utils.assert(Array.isArray(tags), 'Validator tags must be an array');
this.tags = tags || [];

@@ -358,6 +372,5 @@ return this;

var finalizeFns = [];
key = key || '0';
key = key || '<root>';
obj = obj || { '0': value };
errors = errors || {};
errors.add = errors.add || function () { };
errors = errors || new Errors(this);

@@ -368,3 +381,7 @@ // Check vs valid/invalid values

status = false;
errors.add('the value of ' + key + ' is not allowed to be ' + this.__invalids._values[this.__invalids._values.indexOf(value)], keyPath);
var invalidValue = this.__invalids._values[this.__invalids._values.indexOf(value)];
if (invalidValue === '') {
invalidValue = 'empty';
}
errors.add('the value of ' + key + ' is not allowed to be ' + invalidValue, keyPath);
if (this.options.shortCircuit === true) {

@@ -410,7 +427,6 @@ return status;

var result = this.__validators[j](value, obj || { '0': value }, key || '0', errors, keyPath);
var result = this.__validators[j](value, obj || { '0': value }, key, errors, keyPath);
if (!result) {
status = false;
errors.add('not valid', keyPath);
if (this.options.shortCircuit === true) {
if (this.options.shortCircuit === true || validatorName == 'base') { // doesn't make sense to continue validation when type is wrong
return status;

@@ -422,6 +438,5 @@ }

for (var l in finalizeFns) {
var resultFns = this.__validators[finalizeFns[l]](value, obj || { '0': value }, key || '0', errors, keyPath);
var resultFns = this.__validators[finalizeFns[l]](value, obj || { '0': value }, key, errors, keyPath);
if (!resultFns) {
status = false;
errors.add('not valid', keyPath);
if (this.options.shortCircuit === true) {

@@ -434,2 +449,2 @@ return status;

return status;
};
};
// Load modules
var NodeUtil = require('util');
var BaseType = require('./base');

@@ -26,3 +25,3 @@ var Utils = require('../utils');

NodeUtil.inherits(internals.BooleanType, BaseType);
Utils.inherits(internals.BooleanType, BaseType);

@@ -29,0 +28,0 @@

@@ -0,0 +0,0 @@ // Load modules

// Load modules
var NodeUtil = require('util');
var BaseType = require('./base');

@@ -26,6 +25,6 @@ var Utils = require('../utils');

NodeUtil.inherits(internals.FunctionType, BaseType);
Utils.inherits(internals.FunctionType, BaseType);
internals.FunctionType.prototype.__name = "Function";
internals.FunctionType.prototype.__name = 'Function';

@@ -37,3 +36,3 @@

var result = (value === null || typeof value === "function");
var result = (value === null || typeof value === 'function');

@@ -40,0 +39,0 @@ if (!result) {

@@ -10,2 +10,3 @@ // Load modules

var FunctionType = require('./function');
var AnyType = require('./any');

@@ -29,2 +30,3 @@

this.Function = FunctionType;
this.Any = AnyType;

@@ -31,0 +33,0 @@ return this;

// Load modules
var NodeUtil = require('util');
var BaseType = require('./base');

@@ -26,3 +25,3 @@ var Utils = require('../utils');

NodeUtil.inherits(internals.NumberType, BaseType);
Utils.inherits(internals.NumberType, BaseType);

@@ -47,8 +46,8 @@

if (typeof value !== 'number' && typeof value !== 'string') {
errors.add('the value of ' + key + ' must be a number', keyPath);
if ((typeof value !== 'number' && typeof value !== 'string') || isNaN(+value)) {
errors.addLocalized('number.base', key, value, keyPath);
return false;
}
return !isNaN(+value);
return true;
};

@@ -73,3 +72,3 @@ };

if (!result) {
errors.add('the value of ' + key + ' must be larger than (or equal to) ' + n, keyPath);
errors.addLocalized('number.min', key, value, keyPath);
}

@@ -97,3 +96,3 @@

if (!result) {
errors.add('the value of ' + key + ' must be less than (or equal to) ' + n, keyPath);
errors.addLocalized('number.max', key, value, keyPath);
}

@@ -118,3 +117,3 @@ return result;

if (!result) {
errors.add('the value of ' + key + ' must be an integer', keyPath);
errors.addLocalized('number.int', key, value, keyPath);
}

@@ -141,3 +140,3 @@

if (!result) {
errors.add('the value of ' + key + ' must be a float or double', keyPath);
errors.addLocalized('number.float', key, value, keyPath);
}

@@ -144,0 +143,0 @@

// Load modules
var NodeUtil = require('util');
var BaseType = require('./base');

@@ -24,3 +23,3 @@ var Utils = require('../utils');

this._config = config || {};
this._config = config;

@@ -30,3 +29,3 @@ return this;

NodeUtil.inherits(internals.ObjectType, BaseType);
Utils.inherits(internals.ObjectType, BaseType);

@@ -38,4 +37,8 @@

internals.ObjectType.prototype.convert = function (value) {
return (typeof value === 'object' || typeof value === 'undefined') ? value : JSON.parse(value);
try {
return (typeof value === 'object' || typeof value === 'undefined') ? value : JSON.parse(value);
}
catch(err) {
return value;
}
};

@@ -80,3 +83,3 @@

var keys = Object.keys(config);
var keys = Object.keys(config || {});
var unprocessedObject = Utils.clone(obj || {});

@@ -89,11 +92,16 @@ var result = true;

var value = obj[key];
keyPath = keyPath ? topKeyPath + '.' + key : key;
keyPath = keyPath && topKeyPath ? (topKeyPath + '.' + key) : key;
if (typeof itemConfig.validate === 'function' &&
itemConfig.validate(value, obj, key, errors, keyPath) === false) {
return false;
result = false;
if (self.options.shortCircuit) {
return result;
}
}
if (itemConfig.type === 'Object' && value) {
if (itemConfig.type === 'Object' && value !== null && typeof value !== 'undefined') {
traverse(value, itemConfig._config, errors, topKeyPath);

@@ -105,11 +113,20 @@ }

if (self._allowOtherKeys !== true && keys.length) { // Only error on unknown keys when config specifies a structure
Object.keys(unprocessedObject).forEach(function (unprocessedKey) {
// Only error on unknown keys when config specifies a structure.
// Thus new T.Object() allows any keys while T.Object({}) does not.
if (self._allowOtherKeys !== true && typeof config === 'object') {
var unprocessedKeys = Object.keys(unprocessedObject);
for (var i = 0, il = unprocessedKeys.length; i < il; ++i) {
var unprocessedKey = unprocessedKeys[i];
var unprocessedValueType = typeof unprocessedObject[unprocessedKey];
if (unprocessedValueType !== 'function' && unprocessedValueType !== 'undefined') {
errors.add('the key (' + unprocessedKey + ') is not allowed', topKeyPath + '.' + unprocessedKey);
errors.add('the key (' + unprocessedKey + ') is not allowed', (topKeyPath ? (topKeyPath + '.' + unprocessedKey) : unprocessedKey));
if (self.options.shortCircuit === true) {
return false;
}
result = false;
}
});
}
}

@@ -116,0 +133,0 @@

// Load modules
var NodeUtil = require('util');
var BaseType = require('./base');

@@ -27,3 +26,3 @@ var Utils = require('../utils');

NodeUtil.inherits(internals.StringType, BaseType);
Utils.inherits(internals.StringType, BaseType);

@@ -30,0 +29,0 @@

@@ -0,0 +0,0 @@ // Load modules

{
"name": "joi",
"description": "Object schema validation",
"version": "0.3.5",
"version": "0.3.6",
"author": "Van Nguyen <the.gol.effect@gmail.com>",

@@ -23,4 +23,3 @@ "contributors": [

"devDependencies": {
"lab": "0.x.x",
"complexity-report": "0.x.x"
"lab": "0.x.x"
},

@@ -27,0 +26,0 @@ "scripts": {

@@ -21,2 +21,4 @@ <a href="https://github.com/spumko"><img src="https://raw.github.com/spumko/spumko/master/images/from.png" align="right" /></a>

* [Object](#object "Object")
* [Function](#function "Function")
* [Any](#any "Any")
* [Usage](#usage "Usage")

@@ -82,6 +84,4 @@ * [Config Syntax](#config-syntax "Config Syntax")

```javascript
Joi.validate(obj, schema, function (err) {
// err will be set if the object failed to validate against the schema
});
var err = Joi.validate(obj, schema);
// err will be set if the object failed to validate against the schema
```

@@ -98,2 +98,4 @@

* [Object](#object "Object")
* [Function](#function "Function")
* [Any](#any "Any")

@@ -343,2 +345,15 @@ Any custom, user-defined data type is derived from one of the base types (although it may also combine additional types for sub-elements). Thus, there are two valid ways of creating your own types.

#### Function
Function types accept any value that is a function.
*Note: Function has no special methods other than those inherited from BaseType*
#### Any
Accept any type of value where the value is not null. By default the value must not be null but is allowed to be undefined. To change this behavior use either the _'required'_ or _'nullOk'_ methods.
*Note: Any has no special methods other than those inherited from BaseType*
## Usage

@@ -420,2 +435,10 @@

#### Custom Messages
Joi error messages can be updated and replaced with localized versions. Use the `languagePath` option to specify a file path to a JSON file that contains error messages. Each message supports a mustache style template with the following keys:
- `{{key}}` - the schema property that fails validation
- `{{value}}` - the invalid value assigned to the key
#### Skip Functions

@@ -458,2 +481,8 @@

schema.nickname.validate('o', null, null, errors) // => populates errors with all failing constraints
// alternative way
var input = { amount: 2.5 };
var schema = { amount: T.Number().integer().min(3).max(5).noShortCircuit() };
Joi.validate(input, schema);

@@ -493,11 +522,7 @@

Joi.validate(invalidObj, schema, function (err) {
var err = Joi.validate(invalidObj, schema);
if (err) throw err;
if (err) throw err;
});
Joi.validate(validObj, schema, function (err) {
if (err) throw err;
});
var err = Joi.validate(validObj, schema);
if (err) throw err;
```

@@ -521,7 +546,5 @@

Joi.validate(obj, schema, function (err) {
if (err) throw err;
else console.log('Success!');
});
var err = Joi.validate(obj, schema);
if (err) throw err;
else console.log('Success!');
```

@@ -528,0 +551,0 @@

@@ -152,2 +152,50 @@ // Load modules

it('should validate config where the root item is a joi Object and saveConversions setting is enabled', function (done) {
Joi.settings.saveConversions = true;
var config = T.Object({
a: T.String()
});
expect(Joi.validate({ a: 'okay' }, config)).to.be.null;
Joi.settings.saveConversions = false;
done();
});
it('should not alter valid top level objects when saveConversions setting is enabled', function (done) {
Joi.settings.saveConversions = true;
var config = T.Object({
a: T.String()
});
var original = { a: 'okay' };
var validated = { a: 'okay' };
expect(Joi.validate(validated, config)).to.be.null;
expect(validated).to.deep.equal(original);
Joi.settings.saveConversions = false;
done();
});
it('should allow unknown keys in objects if no schema was given', function (done) {
expect(Joi.validate({ foo: 'bar' }, T.Object())).to.not.exist;
done();
});
it('should fail on unkown keys in objects if a schema was given', function (done) {
expect(Joi.validate({ foo: 'bar' }, T.Object({}))).to.exist;
expect(Joi.validate({ foo: 'bar' }, {})).to.exist;
expect(Joi.validate({ foo: 'bar' }, { other: T.Number() })).to.exist;
done();
});
it('should validate an unknown option', function (done) {

@@ -338,3 +386,62 @@

it('should fail validation when parameter is required to be an object but is given as string', function (done) {
var obj = {
a: "a string"
};
var err = Joi.validate(obj, { a: Joi.types.Object({ b: Joi.types.String().required() }) });
expect(err).to.exist;
done();
});
it('should pass validation when parameter is required to be an object and is given correctly as a json string', function (done) {
var obj = {
a: '{"b":"string"}'
};
var err = Joi.validate(obj, { a: Joi.types.Object({ b: Joi.types.String().required() }) });
expect(err).to.be.null;
done();
});
it('should fail validation when parameter is required to be an object but is given as a json string that is incorrect (number instead of string)', function (done) {
var obj = {
a: '{"b":2}'
};
var err = Joi.validate(obj, { a: Joi.types.Object({ b: Joi.types.String().required() }) });
expect(err).to.exist;
done();
});
it('should fail validation when parameter is required to be an Array but is given as string', function (done) {
var obj = {
a: "an array"
};
var err = Joi.validate(obj, { a: Joi.types.Array() });
expect(err).to.exist;
done();
});
it('should pass validation when parameter is required to be an Array and is given correctly as a json string', function (done) {
var obj = {
a: '[1,2]'
};
var err = Joi.validate(obj, { a: Joi.types.Array() });
expect(err).to.be.null;
done();
});
it('should fail validation when parameter is required to be an Array but is given as a json that is incorrect (object instead of array)', function (done) {
var obj = {
a: '{"b":2}'
};
var err = Joi.validate(obj, { a: Joi.types.Object({ b: Joi.types.String().required() }) });
expect(err).to.exist;
done();
});
it('should fail validation when config is an array and fails', function (done) {

@@ -457,2 +564,16 @@

it('there should be more validation errors when short circuit is disabled', function (done) {
var input = { a: 1, b: 2 };
var resultWithShortCircuit = Joi.validate(input, T.Object({}));
var resultWithoutShortCircuit = Joi.validate(input, T.Object({}).noShortCircuit());
expect(resultWithShortCircuit).to.exist
expect(resultWithoutShortCircuit).to.exist
expect(resultWithoutShortCircuit._errors.length).to.be.greaterThan(resultWithShortCircuit._errors.length);
done();
});
internals.routeSchema = {

@@ -459,0 +580,0 @@ method: T.String().invalid('head').required(),

@@ -0,0 +0,0 @@ // Load modules

@@ -0,0 +0,0 @@ // Load modules

@@ -29,3 +29,4 @@ // Load modules

N = Joi.types.Number,
S = Joi.types.String;
S = Joi.types.String,
O = Joi.types.Object;

@@ -73,4 +74,3 @@ it('should have mixins', function (done) {

var result = A().convert('asdf');
expect(result.length).to.equal(1);
expect(result[0]).to.equal('asdf');
expect(result).to.equal('asdf');
done();

@@ -183,2 +183,20 @@ });

it('should validate array of objects with schema', function (done) {
verifyBehavior(A().includes(O({ h1: N().required()})), [
[
[{ h1: 1 }, { h1: 2 }, { h1: 3 }],
true
],
[
[{ h2: 1, h3: 'somestring' }, { h1: 2 }, { h1: 3 }],
false
],
[
[1, 2, [1]],
false
]
], done);
});
it('should not validate array of unallowed mixed types (Array)', function (done) {

@@ -197,4 +215,17 @@

});
it('should not throw when using includes', function (done) {
var schema = {
arr: Joi.types.Array().includes(Joi.types.Number().integer())
};
var input = { arr: [1, 2, 2.1] };
var err = Joi.validate(input, schema);
expect(err).to.exist;
done();
});
});
});
});

@@ -86,5 +86,4 @@ // Load modules

var b1 = new B();
var b2 = new B();
var result = b1.with(b2);
var b = new B();
var result = b.with('test');

@@ -97,5 +96,4 @@ expect(result.__checks).to.include('with');

var b1 = new B();
var b2 = new B();
var result = b1.with(b2);
var b = new B();
var result = b.with('test');

@@ -108,4 +106,4 @@ expect(result.validate('test')).to.equal(false);

var b1 = new B();
var result = b1._with(null);
var b = new B();
var result = b._with(null);

@@ -115,2 +113,32 @@ expect(result(null)).to.equal(true);

});
it('should throw an error when a parameter is not a string', function (done) {
var b = new B();
var error = false;
try {
b.with([]);
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
try {
b.with({});
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
try {
b.with(123);
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
done();
});
});

@@ -122,5 +150,4 @@

var b1 = new B();
var b2 = new B();
var result = b1.without(b2);
var b = new B();
var result = b.without('test');

@@ -133,5 +160,4 @@ expect(result.__checks).to.include('without');

var b1 = new B();
var b2 = new B();
var result = b1.without(b2);
var b = new B();
var result = b.without('test');

@@ -141,2 +167,32 @@ expect(result.validate('test')).to.equal(true);

});
it('should throw an error when a parameter is not a string', function (done) {
var b = new B();
var error = false;
try {
b.without([]);
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
try {
b.without({});
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
try {
b.without(123);
error = false;
} catch (e) {
error = true;
}
expect(error).to.equal(true);
done();
});
});

@@ -143,0 +199,0 @@

@@ -0,0 +0,0 @@ // Load modules

@@ -0,0 +0,0 @@ // Load modules

@@ -0,0 +0,0 @@ // Load modules

@@ -413,2 +413,13 @@ // Load modules

});
describe('error message', function () {
it('should display correctly for int type', function (done) {
var t = N().integer();
var result = Joi.validate('', t);
expect(result.message).to.contain('integer');
done();
});
});
});

@@ -43,2 +43,9 @@ // Load modules

it('should convert a non-json string as a string', function (done) {
var result = O().convert('a string');
expect(result).to.be.equal('a string');
done();
});
it('should validate an object', function (done) {

@@ -45,0 +52,0 @@

@@ -114,2 +114,11 @@ // Load modules

it('should, when .required(), print a friend error message for an empty string', function (done) {
var t = S().required();
var result = Joi.validate('', t);
expect(result.message).to.contain('be empty');
done();
});
it('should, when .required(), validate non-empty strings', function (done) {

@@ -116,0 +125,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc