freeman-check
Advanced tools
Comparing version 1.1.0 to 2.0.0
247
index.js
@@ -1,2 +0,2 @@ | ||
//freeman-env | ||
//freeman-check | ||
//usage: | ||
@@ -6,24 +6,43 @@ /* | ||
var some_object = { | ||
var object = { | ||
name: "Nabil Freeman", | ||
favourite_films: "Face/Off, Bad Lieutenant, The Wicker Man", | ||
favourite_films: [ | ||
"Face/Off", | ||
"Bad Lieutenant", | ||
"The Wicker Man" | ||
] | ||
} | ||
var check = Check(some_object, { | ||
name: "string", | ||
favourite_films: "array", | ||
profile: { | ||
email: "string", | ||
sign_in_count: "number" | ||
} | ||
var schema = { | ||
type: "object", | ||
properties: { | ||
name: { | ||
type: "string" | ||
} | ||
email: { | ||
type: "string", | ||
format: "email" | ||
}, | ||
favourite_films: { | ||
type: "array", | ||
items: { | ||
type: "string" | ||
} | ||
} | ||
}, | ||
required: ["name", "email", "favourite_films"] | ||
}; | ||
Check.test(some_object, schema).then(function(object){ | ||
console.log(object) //object === some_object | ||
}).catch(function(error){ | ||
console.log(error.message) // "`email` is missing." // "`email` is malformatted." // etc... | ||
console.log(error.schema) //error.schema === schema | ||
}) | ||
*/ | ||
if(check instanceof Check.Error){ | ||
console.log(check.message); | ||
} | ||
var Promise = require('bluebird'); | ||
var Validate = require('jsonschema').validate; | ||
var anora = require('anora'); | ||
The above will throw a `not found` error as `profile` is missing. | ||
*/ | ||
//override error object so we can have whatever we want in the message field. | ||
@@ -33,170 +52,58 @@ var CheckError = function(message){ | ||
} | ||
CheckError.prototype = new Error(); | ||
var joinOptionalParameters = function(item, required_format, optional_root_object){ | ||
if(optional_root_object === undefined){ | ||
return required_format; | ||
} | ||
var main = { | ||
test: function(object, schema){ | ||
return new Promise(function(resolve, reject){ | ||
if(object === null || object === undefined){ | ||
reject(new CheckError('The first argument is null or undefined.')) | ||
} | ||
var item_keys = Object.keys(item); | ||
var required_keys = Object.keys(required_format); | ||
var optional_keys = Object.keys(optional_root_object); | ||
if(schema === null || schema === undefined){ | ||
reject(new CheckError('The second argument is null or undefined.')) | ||
} | ||
//check if there are more keys in the root object than the desired format. | ||
//if there are, this means that there might be an optional parameter passed. | ||
if(item_keys.length <= required_keys.length){ | ||
return required_format; //there are not more keys. | ||
} | ||
//validate. | ||
var result = Validate(object, schema); | ||
//there are more keys in the item than the required format... | ||
//so let's join the optional object onto the map we are testing against. | ||
optional_keys.forEach(function(key){ | ||
required_format[key] = optional_root_object[key]; | ||
}) | ||
return required_format; | ||
}; | ||
var type = function(element, already_defined){ | ||
var type_string; | ||
if(element instanceof Array){ | ||
type_string = "array"; | ||
} else if(element === null){ | ||
type_string = "null"; | ||
} else if(typeof element === "object"){ | ||
type_string = "object"; | ||
} else { | ||
if(already_defined){ | ||
type_string = element; | ||
} else { | ||
type_string = typeof element; | ||
} | ||
} | ||
return type_string | ||
} | ||
//recursive function for nested objects. | ||
var recurse = function(child, required){ | ||
var child_type = type(child, false); | ||
var required_type = type(required, true); | ||
if(child_type === "array"){ | ||
if(required_type === "array"){ | ||
//end the recursion - we are not testing inside arrays yet. | ||
} else { | ||
throw new CheckError({ | ||
message: "You sent an: 'array' where we were expecting" + required_type | ||
}); | ||
} | ||
} else { | ||
var required_keys = Object.keys(required); | ||
var child_keys = Object.keys(child); | ||
//check for invalid keys in this object level by matching the keys of both objects against each other. | ||
var invalid_keys = []; | ||
child_keys.forEach(function(key){ | ||
if(required[key] === undefined){ | ||
invalid_keys.push(key); | ||
//if there are no errors, the object is valid. | ||
if(result.errors.length === 0){ | ||
resolve(object); | ||
return; | ||
} | ||
}) | ||
if(invalid_keys.length > 0){ | ||
throw new CheckError({ | ||
message: "The following keys are not allowed and should be removed: " + invalid_keys.join(', ') | ||
}); | ||
} | ||
////end first invalid key check | ||
//init error string | ||
var error_message = ""; | ||
result.errors.forEach(function(error){ | ||
var subject = error.argument; //name, email, etc. | ||
var problem = "is incorrect"; //default | ||
//if the user has sent less keys than in the required spec then we can deduce that there are keys missing. | ||
if(required_keys.length > child_keys.length){ | ||
var missing_keys = []; | ||
required_keys.forEach(function(key){ | ||
if(child_keys.indexOf(key) === -1){ | ||
missing_keys.push(key); | ||
//assign plain english to error messages. | ||
switch(error.name){ | ||
case "required": | ||
problem = "is missing"; | ||
break; | ||
case "format": | ||
problem = "is malformatted"; | ||
break; | ||
case "type": | ||
subject = error.property.replace("instance.", ""); | ||
problem = 'needs to be ' + anora(error.schema.type) + ' `' + error.schema.type + '`' | ||
break; | ||
} | ||
}) | ||
throw new CheckError({ | ||
message: "The following object keys are missing from your request: " + missing_keys.join(', ') | ||
}) | ||
} else if(required_keys.length < child_keys.length) { | ||
//the contents of this statement should never run - our first invalid key check will protect against having more than the required number of keys. | ||
//we'll keep it as a precautionary measure for now. | ||
var invalid_keys = []; | ||
//concatenate all validation errors. | ||
error_message += ('`' + subject + '` ' + problem + '. '); | ||
}); | ||
child_keys.forEach(function(key){ | ||
if(required_keys.indexOf(key) === -1){ | ||
invalid_keys.push(key); | ||
} | ||
}) | ||
//remove last character from concatenated error message. | ||
error_message = error_message.slice(0, -1); | ||
throw new CheckError({ | ||
message: "The following object keys are not allowed and should be removed: " + invalid_keys.join(', ') | ||
}) | ||
} | ||
var error = new CheckError(error_message); | ||
child_keys.forEach(function(key){ | ||
//if we got this far, all keys are allowed within this child object. | ||
var child_type = type(child[key], false); | ||
var required_type = type(required[key], true); | ||
error.schema = schema; | ||
//now let's check if it matches our spec. | ||
if(child_type === "object" && required_type === "object"){ | ||
//both of our maps have objects in the same position which means we need to go deeper and search through them. | ||
//activate the recurse function... | ||
recurse(child[key], required[key]) | ||
} else if(child_type === "array" && required_type === "array"){ | ||
//both of our maps have arrays in the same position which means we need to go deeper and search through them. | ||
//activate the recurse function... | ||
recurse(child[key], required[key]) | ||
} else if(required_type.indexOf(child_type) > -1){ | ||
//do nothing! we can stop the recursion on this one. the key is a match. | ||
} else { | ||
//there is a type mismatch... throw type error. | ||
throw new CheckError({ | ||
message: "Invalid type for key: \'" + key + "'. You sent: '" + child_type + "'. It needs to be: '" + required_type + "'." | ||
}); | ||
} | ||
}); | ||
} | ||
} | ||
var main = { | ||
test: function(item, required_format, optional_parameters){ | ||
if(item === null || item === undefined){ | ||
return new CheckError('The first argument is null or undefined.') | ||
} | ||
if(item === null || item === undefined){ | ||
return new CheckError('The second argument is null or undefined.') | ||
} | ||
try{ | ||
required_format = joinOptionalParameters(item, required_format, optional_parameters); | ||
recurse(item, required_format); | ||
return true; | ||
} catch(error) { | ||
if(error instanceof CheckError){ | ||
error.message.full_expected_payload = required_format; | ||
return error; | ||
} else { | ||
return new CheckError('System error. Our coders have been notified of this event.') | ||
} | ||
} | ||
reject(error); | ||
}) | ||
}, | ||
@@ -203,0 +110,0 @@ |
{ | ||
"name": "freeman-check", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"description": "Easy type and format checking on JavaScript objects", | ||
@@ -18,3 +18,8 @@ "main": "index.js", | ||
"homepage": "https://github.com/freeman-industries/freeman-check#readme", | ||
"license": "ISC" | ||
"license": "ISC", | ||
"dependencies": { | ||
"anora": "^1.0.1", | ||
"bluebird": "^3.4.6", | ||
"jsonschema": "^1.1.0" | ||
} | ||
} |
@@ -13,21 +13,37 @@ # freeman-check | ||
var user = { | ||
var object = { | ||
name: "Nabil Freeman", | ||
favourite_films: ["Face/Off", "Bad Lieutenant", "The Wicker Man"] | ||
favourite_films: [ | ||
"Face/Off", | ||
"Bad Lieutenant", | ||
"The Wicker Man" | ||
] | ||
} | ||
var check = Check(user, { | ||
name: "string", | ||
favourite_films: "array", | ||
profile: { | ||
email: "string", | ||
sign_in_count: "number" | ||
} | ||
var schema = { | ||
type: "object", | ||
properties: { | ||
name: { | ||
type: "string" | ||
} | ||
email: { | ||
type: "string", | ||
format: "email" | ||
}, | ||
favourite_films: { | ||
type: "array", | ||
items: { | ||
type: "string" | ||
} | ||
} | ||
}, | ||
required: ["name", "email", "favourite_films"] | ||
}; | ||
Check.test(some_object, schema).then(function(object){ | ||
console.log(object) //object === some_object | ||
}).catch(function(error){ | ||
console.log(error.message) // "`email` is missing." // "`email` is malformatted." // etc... | ||
console.log(error.schema) //error.schema === schema | ||
}) | ||
if(check instanceof Check.Error){ | ||
console.log(check.message); | ||
} | ||
``` | ||
The above will throw a `not found` error as `profile` is missing. | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
48
4138
3
92
1
+ Addedanora@^1.0.1
+ Addedbluebird@^3.4.6
+ Addedjsonschema@^1.1.0
+ Addedanora@1.1.0(transitive)
+ Addedbluebird@3.7.2(transitive)
+ Addedjsonschema@1.5.0(transitive)