diff --git a/nodejs/utils/object_validate.js b/nodejs/utils/object_validate.js index 35c3d21..1958802 100644 --- a/nodejs/utils/object_validate.js +++ b/nodejs/utils/object_validate.js @@ -21,22 +21,37 @@ function processKeys(map, data, partial){ for(let key of Object.keys(map)){ + // Do not require "isRequired" fields for partial validation, useful for + // updates. if(!map[key].always && partial && !data.hasOwnProperty(key)) continue; + // Make sure required keys are present if(!partial && map[key].isRequired && !data.hasOwnProperty(key)){ errors.push({key, message:`${key} is required.`}); continue; - } + } + // Remove undefined keys unless they have a default option or are a + // relation + if(data[key] === undefined){ + console.log('undefined key:', key, data[key], map[key], map[key].default); + if(!map[key].default){ + if(map[key].model && !map[key].type) continue; + continue; + } + } + + // Check the type of the key if(data.hasOwnProperty(key) && map[key].type && typeof(data[key]) !== map[key].type){ errors.push({key, message:`${key} is not ${map[key].type} type.`}); continue; } - // console.log(key, data[key], map[key].default, data.hasOwnProperty(key) && data[key] !== undefined ? data[key] : returnOrCall(map[key].default)) - + // Add the key to the process object to be returned and set any default + // if the key is blank out[key] = data.hasOwnProperty(key) && data[key] !== undefined ? data[key] : returnOrCall(map[key].default); + // Check for type specific validations, ie: string length if(data.hasOwnProperty(key) && process_type[map[key].type]){ let typeError = process_type[map[key].type](map[key], data[key]); if(typeError){ @@ -47,8 +62,9 @@ function processKeys(map, data, partial){ } } + // Check for errors, throw validation error if any if(errors.length !== 0){ - throw new ObjectValidateError(errors); + throw ObjectValidateError(errors); return {__errors__: errors}; } @@ -56,6 +72,7 @@ function processKeys(map, data, partial){ } function parseFromString(map, data){ + // Use the key maps data type to return string values to native let types = { boolean: function(value){ return value === 'false' ? false : true }, number: Number, @@ -80,11 +97,14 @@ function parseToString(data){ return (types[typeof(data)] || String)(data); } -function ObjectValidateError(message){ - this.name = 'ObjectValidateError'; - this.message = (message || {}); - this.keys = (message || {}) - this.status = 422; +function ObjectValidateError(keys, message){ + let error = new Error('ObjectValidateError') + error.name = "ObjectValidateError" + error.message = message || `Invalid Keys: ${message}` + error.keys = (keys || {}); + error.status = 422; + + return error } ObjectValidateError.prototype = Error.prototype; diff --git a/nodejs/utils/redis_model.js b/nodejs/utils/redis_model.js index c712598..9b62456 100644 --- a/nodejs/utils/redis_model.js +++ b/nodejs/utils/redis_model.js @@ -29,6 +29,22 @@ class QueryHelper{ } class Table{ + static errors = { + ObjectValidateError: objValidate.ObjectValidateError, + EntryNameUsed: ()=>{ + let error = new Error('EntryNameUsed'); + error.name = 'EntryNameUsed'; + error.message = `${this.prototype.constructor.name}:${data[this._key]} already exists`; + error.keys = [{ + key: this._key, + message: `${this.prototype.constructor.name}:${data[this._key]} already exists` + }] + error.status = 409; + + return error; + } + } + static redisClient = client; static models = {} @@ -139,6 +155,10 @@ class Table{ return out; } + static findall(...args){ + return this.listDetail(...args); + } + static async create(data){ // Add a entry to this redis table. try{