You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
8.6 KiB
213 lines
8.6 KiB
"use strict"; |
|
var __defProp = Object.defineProperty; |
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols; |
|
var __hasOwnProp = Object.prototype.hasOwnProperty; |
|
var __propIsEnum = Object.prototype.propertyIsEnumerable; |
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; |
|
var __spreadValues = (a, b) => { |
|
for (var prop in b || (b = {})) |
|
if (__hasOwnProp.call(b, prop)) |
|
__defNormalProp(a, prop, b[prop]); |
|
if (__getOwnPropSymbols) |
|
for (var prop of __getOwnPropSymbols(b)) { |
|
if (__propIsEnum.call(b, prop)) |
|
__defNormalProp(a, prop, b[prop]); |
|
} |
|
return a; |
|
}; |
|
const _ = require("lodash"); |
|
const Utils = require("./utils"); |
|
const sequelizeError = require("./errors"); |
|
const DataTypes = require("./data-types"); |
|
const BelongsTo = require("./associations/belongs-to"); |
|
const validator = require("./utils/validator-extras").validator; |
|
const { promisify } = require("util"); |
|
class InstanceValidator { |
|
constructor(modelInstance, options) { |
|
options = __spreadValues({ |
|
hooks: true |
|
}, options); |
|
if (options.fields && !options.skip) { |
|
options.skip = _.difference(Object.keys(modelInstance.constructor.rawAttributes), options.fields); |
|
} else { |
|
options.skip = options.skip || []; |
|
} |
|
this.options = options; |
|
this.modelInstance = modelInstance; |
|
this.validator = validator; |
|
this.errors = []; |
|
this.inProgress = false; |
|
} |
|
async _validate() { |
|
if (this.inProgress) |
|
throw new Error("Validations already in progress."); |
|
this.inProgress = true; |
|
await Promise.all([ |
|
this._perAttributeValidators(), |
|
this._customValidators() |
|
]); |
|
if (this.errors.length) { |
|
throw new sequelizeError.ValidationError(null, this.errors); |
|
} |
|
} |
|
async validate() { |
|
return await (this.options.hooks ? this._validateAndRunHooks() : this._validate()); |
|
} |
|
async _validateAndRunHooks() { |
|
const runHooks = this.modelInstance.constructor.runHooks.bind(this.modelInstance.constructor); |
|
await runHooks("beforeValidate", this.modelInstance, this.options); |
|
try { |
|
await this._validate(); |
|
} catch (error) { |
|
const newError = await runHooks("validationFailed", this.modelInstance, this.options, error); |
|
throw newError || error; |
|
} |
|
await runHooks("afterValidate", this.modelInstance, this.options); |
|
return this.modelInstance; |
|
} |
|
async _perAttributeValidators() { |
|
const validators = []; |
|
_.forIn(this.modelInstance.rawAttributes, (rawAttribute, field) => { |
|
if (this.options.skip.includes(field)) { |
|
return; |
|
} |
|
const value = this.modelInstance.dataValues[field]; |
|
if (value instanceof Utils.SequelizeMethod) { |
|
return; |
|
} |
|
if (!rawAttribute._autoGenerated && !rawAttribute.autoIncrement) { |
|
this._validateSchema(rawAttribute, field, value); |
|
} |
|
if (Object.prototype.hasOwnProperty.call(this.modelInstance.validators, field)) { |
|
validators.push(this._singleAttrValidate(value, field, rawAttribute.allowNull)); |
|
} |
|
}); |
|
return await Promise.all(validators); |
|
} |
|
async _customValidators() { |
|
const validators = []; |
|
_.each(this.modelInstance.constructor.options.validate, (validator2, validatorType) => { |
|
if (this.options.skip.includes(validatorType)) { |
|
return; |
|
} |
|
const valprom = this._invokeCustomValidator(validator2, validatorType).catch(() => { |
|
}); |
|
validators.push(valprom); |
|
}); |
|
return await Promise.all(validators); |
|
} |
|
async _singleAttrValidate(value, field, allowNull) { |
|
if ((value === null || value === void 0) && !allowNull) { |
|
return; |
|
} |
|
const validators = []; |
|
_.forIn(this.modelInstance.validators[field], (test, validatorType) => { |
|
if (["isUrl", "isURL", "isEmail"].includes(validatorType)) { |
|
if (typeof test === "object" && test !== null && test.msg) { |
|
test = { |
|
msg: test.msg |
|
}; |
|
} else if (test === true) { |
|
test = {}; |
|
} |
|
} |
|
if (typeof test === "function") { |
|
validators.push(this._invokeCustomValidator(test, validatorType, true, value, field)); |
|
return; |
|
} |
|
if (value === null || value === void 0) { |
|
return; |
|
} |
|
const validatorPromise = this._invokeBuiltinValidator(value, test, validatorType, field); |
|
validatorPromise.catch(() => { |
|
}); |
|
validators.push(validatorPromise); |
|
}); |
|
return Promise.all(validators.map((validator2) => validator2.catch((rejection) => { |
|
const isBuiltIn = !!rejection.validatorName; |
|
this._pushError(isBuiltIn, field, rejection, value, rejection.validatorName, rejection.validatorArgs); |
|
}))); |
|
} |
|
async _invokeCustomValidator(validator2, validatorType, optAttrDefined, optValue, optField) { |
|
let isAsync = false; |
|
const validatorArity = validator2.length; |
|
let asyncArity = 1; |
|
let errorKey = validatorType; |
|
let invokeArgs; |
|
if (optAttrDefined) { |
|
asyncArity = 2; |
|
invokeArgs = optValue; |
|
errorKey = optField; |
|
} |
|
if (validatorArity === asyncArity) { |
|
isAsync = true; |
|
} |
|
if (isAsync) { |
|
try { |
|
if (optAttrDefined) { |
|
return await promisify(validator2.bind(this.modelInstance, invokeArgs))(); |
|
} |
|
return await promisify(validator2.bind(this.modelInstance))(); |
|
} catch (e) { |
|
return this._pushError(false, errorKey, e, optValue, validatorType); |
|
} |
|
} |
|
try { |
|
return await validator2.call(this.modelInstance, invokeArgs); |
|
} catch (e) { |
|
return this._pushError(false, errorKey, e, optValue, validatorType); |
|
} |
|
} |
|
async _invokeBuiltinValidator(value, test, validatorType, field) { |
|
const valueString = String(value); |
|
if (typeof validator[validatorType] !== "function") { |
|
throw new Error(`Invalid validator function: ${validatorType}`); |
|
} |
|
const validatorArgs = this._extractValidatorArgs(test, validatorType, field); |
|
if (!validator[validatorType](valueString, ...validatorArgs)) { |
|
throw Object.assign(new Error(test.msg || `Validation ${validatorType} on ${field} failed`), { validatorName: validatorType, validatorArgs }); |
|
} |
|
} |
|
_extractValidatorArgs(test, validatorType, field) { |
|
let validatorArgs = test.args || test; |
|
const isLocalizedValidator = typeof validatorArgs !== "string" && ["isAlpha", "isAlphanumeric", "isMobilePhone"].includes(validatorType); |
|
if (!Array.isArray(validatorArgs)) { |
|
if (validatorType === "isImmutable") { |
|
validatorArgs = [validatorArgs, field, this.modelInstance]; |
|
} else if (isLocalizedValidator || validatorType === "isIP") { |
|
validatorArgs = []; |
|
} else { |
|
validatorArgs = [validatorArgs]; |
|
} |
|
} else { |
|
validatorArgs = validatorArgs.slice(0); |
|
} |
|
return validatorArgs; |
|
} |
|
_validateSchema(rawAttribute, field, value) { |
|
if (rawAttribute.allowNull === false && (value === null || value === void 0)) { |
|
const association = Object.values(this.modelInstance.constructor.associations).find((association2) => association2 instanceof BelongsTo && association2.foreignKey === rawAttribute.fieldName); |
|
if (!association || !this.modelInstance.get(association.associationAccessor)) { |
|
const validators = this.modelInstance.validators[field]; |
|
const errMsg = _.get(validators, "notNull.msg", `${this.modelInstance.constructor.name}.${field} cannot be null`); |
|
this.errors.push(new sequelizeError.ValidationErrorItem(errMsg, "notNull Violation", field, value, this.modelInstance, "is_null")); |
|
} |
|
} |
|
if (rawAttribute.type instanceof DataTypes.STRING || rawAttribute.type instanceof DataTypes.TEXT || rawAttribute.type instanceof DataTypes.CITEXT) { |
|
if (Array.isArray(value) || _.isObject(value) && !(value instanceof Utils.SequelizeMethod) && !Buffer.isBuffer(value)) { |
|
this.errors.push(new sequelizeError.ValidationErrorItem(`${field} cannot be an array or an object`, "string violation", field, value, this.modelInstance, "not_a_string")); |
|
} |
|
} |
|
} |
|
_pushError(isBuiltin, errorKey, rawError, value, fnName, fnArgs) { |
|
const message = rawError.message || rawError || "Validation error"; |
|
const error = new sequelizeError.ValidationErrorItem(message, "Validation error", errorKey, value, this.modelInstance, fnName, isBuiltin ? fnName : void 0, isBuiltin ? fnArgs : void 0); |
|
error[InstanceValidator.RAW_KEY_NAME] = rawError; |
|
this.errors.push(error); |
|
} |
|
} |
|
InstanceValidator.RAW_KEY_NAME = "original"; |
|
module.exports = InstanceValidator; |
|
module.exports.InstanceValidator = InstanceValidator; |
|
module.exports.default = InstanceValidator; |
|
//# sourceMappingURL=instance-validator.js.map
|
|
|