UNPKG

celeritas

Version:

This is an API service framework which supports API requests over HTTP & WebSockets.

150 lines (130 loc) 6.74 kB
'use strict'; const mongoose = require('mongoose'); const lodash = require('lodash'); //this method is used to validate data for a call. You pass the schema, and input data into it, and it will return an error if the input data fails anything. function validate (validationType, apiRoute, schema, data, propertyName = "data") { switch (validationType) { case "mongoose": { try { var s = mongoose.Schema(schema), model; model = mongoose.model(apiRoute); var tryData = new model(data); return Promise.resolve(tryData.toJSON()); } catch (err) { return Promise.resolve(err); } } //"native" default: { var s = lodash.cloneDeep(schema); return Promise.resolve(_validate(s, data, propertyName)); } } } //Subroutine used by the validate method. function _validate (schema, data, propertyName, isArrayItem = false) { for (var i in schema) { //If the schema key is "$any", then the schema value should be an array of possible validation checks, where the first fulfilled check is the data that's returned instead of $any. if (i == "$any") { var hasSuccess = false; var firstError = null; for (var combo in schema[i]) { var r = _validate(schema[i][combo], JSON.parse(JSON.stringify(data)), propertyName); if (firstError == null && r instanceof Error) firstError = r; else if (!(r instanceof Error)) { try { Object.assign(schema, schema[i][combo]); Object.assign(data, r); delete schema[i]; firstError = null; } catch (err) { return err; } break; } } if (firstError != null) return firstError; break; } if (data !== null && typeof data[i] == "undefined") { if (typeof schema[i].default !== "undefined") data[i] = schema[i].default; else if (schema[i] instanceof Array) data[i] = []; } //for each schema property, if the field is required (assume required if not defined), return an error if that field is missing in the input data. if (data !== null && typeof data[i] == "undefined" && typeof schema[i].type != 'undefined') { if (typeof schema[i].required !== "undefined" && schema[i].required == true) return new Error("400 - Bad Request: The parameter '" + propertyName + "." + i + "' is a required field, please try again."); } if (["string", "function"].indexOf(typeof schema[i]) > -1) schema[i] = {type: schema[i]}; if (schema[i].type instanceof Function && ['String', 'Number', 'Date', 'Boolean', 'Object'].indexOf(schema[i].type.name) > -1) schema[i].type = schema[i].type.name.toLowerCase(); } for (var i in data) { var propertyId = isArrayItem ? propertyName : propertyName + "." + i; if (typeof schema[i] !== "undefined") { //If the schema[i].type is still an object, then it's another schema declaration. Iterate down through the object. if (!(schema[i] instanceof Array) && (typeof schema[i].type == "undefined" || typeof schema[i].type === "object")) { if (typeof data[i] == "undefined") data[i] = {}; var r = _validate(schema[i], data[i], propertyId); if (r instanceof Error) return r; else data[i] = r; } else { if (typeof schema[i].type == "function") { var r = schema[i].type(data[i]); if (r == false) return new Error("400 - Bad Request: The parameter '" + propertyId + "' failed verification check '" + schema[i].type.name + "'. Please try again."); } else if (schema[i] instanceof Array) { if (data[i] instanceof Array == false) { if (typeof data[i] == "undefined") data[i] = []; else return new Error("400 - Bad Request: The parameter '" + propertyId + "' should be an array of objects. Please try again."); } var checkAgainst = {_item: schema[i][0]}; for (var dataItem in data[i]) { var r = _validate(checkAgainst, {_item: data[i][dataItem]}, propertyId + "[" + dataItem + "]", true); if (r instanceof Error) return r; else data[i][dataItem] = r._item; } } else if (schema[i].type !== "*") { if (schema[i].type == "date") { if (data[i] != null) { var tryDate = Date.parse(data[i]); if (isNaN(tryDate)) return new Error("400 - Bad Request: The parameter '" + propertyId + "' cannot be parsed as a date. Please try again."); else data[i] = new Date(tryDate); } } else if (typeof data[i] != schema[i].type.toLowerCase()) { if (typeof data[i] == "number" && schema[i].type == "string") { data[i] = data[i].toString(); } else if (data[i] !== null && (typeof schema[i].required == "undefined" || schema[i].required == true)) return new Error("400 - Bad Request: The parameter '" + propertyId + "' should be of type '" + schema[i].type.toLowerCase() + "'. Please try again."); } if (typeof data[i] == "string" && (typeof schema[i].length !== "undefined" && data[i].length < schema[i].length)) return new Error("400 - Bad Request: The paramater '" + propertyId + "' must be at least '" + schema[i].length + "' characters long. Please try again."); } } } else delete data[i]; } return data; } module.exports = validate;