@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
162 lines (158 loc) • 8.22 kB
JavaScript
'use strict';
var tslib_es6 = require('../external/tslib/tslib.es6.js');
var mustMatchOneOfSchemasErrorType_enum = require('../enum/validator/must-match-one-of-schemas-error-type.enum.js');
var exception_utility = require('../utility/error/exception.utility.js');
var classValidator = require('class-validator');
// eslint-disable-next-line @elsikora/typescript/naming-convention
exports.MustMatchOneOfSchemasConstraint = class MustMatchOneOfSchemasConstraint {
allowedValues = [];
discriminatorField = null;
discriminatorValue = null;
errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.UNKNOWN;
/**
* Provides a custom error message based on the type of validation failure
* @param {ValidationArguments} _arguments - Validation arguments containing property information
* @returns {string} A descriptive error message explaining why validation failed
*/
defaultMessage(_arguments) {
const propertyName = _arguments.property;
switch (this.errorType) {
case mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.INVALID_DISCRIMINATOR: {
const schemasList = this.allowedValues
.map((value) => {
return `'${value}'`;
})
.join(", ");
return `${propertyName} has invalid discriminator value '${String(this.discriminatorValue)}' for field '${String(this.discriminatorField)}'. must be one of: ${schemasList}`;
}
case mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.MISSING_DISCRIMINATOR: {
return `${propertyName} is missing required discriminator field '${String(this.discriminatorField)}'`;
}
case mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH: {
const schemasList = this.allowedValues
.map((value) => {
return `'${value}'`;
})
.join(", ");
return `${propertyName} must match one of the schemas: ${schemasList}`;
}
case mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.UNKNOWN: {
return `${propertyName} must match one of the valid schemas`;
}
default: {
return `${propertyName} must match one of the valid schemas`;
}
}
}
/**
* Validates whether an object matches one of the allowed schemas based on its discriminator field
* @param {unknown} value - The value being validated
* @param {ValidationArguments} _arguments - Validation arguments containing constraints
* @returns {boolean} True if the value matches a valid schema, false otherwise
*/
validate(value, _arguments) {
if (!value || typeof value !== "object" || Array.isArray(value)) {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH;
this.prepareAllowedSchemas(_arguments);
return false;
}
const valueAsRecord = value;
if (Object.keys(valueAsRecord).length === 0) {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH;
this.prepareAllowedSchemas(_arguments);
return false;
}
const constraints = _arguments.constraints;
if (!constraints?.[0]?.discriminator) {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.UNKNOWN;
return false;
}
try {
const discriminator = constraints[0].discriminator;
if (!discriminator.propertyName || typeof discriminator.propertyName !== "string") {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.UNKNOWN;
return false;
}
this.discriminatorField = discriminator.propertyName;
if (!(discriminator.propertyName in valueAsRecord)) {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.MISSING_DISCRIMINATOR;
return false;
}
const discriminatorValue = valueAsRecord[discriminator.propertyName];
if (typeof discriminatorValue !== "string" || discriminatorValue === "") {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.INVALID_DISCRIMINATOR;
this.discriminatorValue = String(discriminatorValue);
this.prepareAllowedSchemas(_arguments);
return false;
}
this.discriminatorValue = discriminatorValue;
if (!discriminator.mapping || typeof discriminator.mapping !== "object") {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH;
this.prepareAllowedSchemas(_arguments);
return false;
}
this.prepareAllowedSchemas(_arguments);
if (!this.allowedValues.includes(discriminatorValue)) {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.INVALID_DISCRIMINATOR;
return false;
}
return true;
}
catch {
this.errorType = mustMatchOneOfSchemasErrorType_enum.EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH;
this.prepareAllowedSchemas(_arguments);
return false;
}
}
/**
* Prepares the list of allowed discriminator values based on validation constraints
* @param {ValidationArguments} _arguments - Validation arguments containing constraints
* @returns {void}
* @private
*/
prepareAllowedSchemas(_arguments) {
this.allowedValues = [];
const constraints = _arguments.constraints;
if (!constraints?.[0]) {
return;
}
const { discriminator } = constraints[0];
if (!discriminator?.mapping) {
return;
}
this.allowedValues = Object.keys(discriminator.mapping);
}
};
exports.MustMatchOneOfSchemasConstraint = tslib_es6.__decorate([
classValidator.ValidatorConstraint({ async: false, name: "must-match-one-of-schemas" })
], exports.MustMatchOneOfSchemasConstraint);
/**
* Decorator that checks if the object matches one of the schemas based on the discriminator field
* @param {IMustMatchOneOfSchemasDiscriminatorConfig} discriminatorConfig - Configuration for the discriminator
* @param {ValidationOptions} [validationOptions] - Validation options
* @returns {PropertyDecorator} - Decorator
*/
function MustMatchOneOfSchemasValidator(discriminatorConfig, validationOptions) {
return function (target, propertyKey) {
if (typeof propertyKey !== "string") {
throw exception_utility.ErrorException("MatchesOneOfSchemas decorator can only be applied to string properties");
}
if (!discriminatorConfig?.discriminator) {
throw exception_utility.ErrorException("discriminatorConfig must contain a discriminator property");
}
const discriminator = discriminatorConfig.discriminator;
if (!discriminator.propertyName || !discriminator.mapping) {
throw exception_utility.ErrorException("discriminator must contain propertyName and mapping properties");
}
classValidator.registerDecorator({
constraints: [discriminatorConfig],
name: "must-match-one-of-schemas",
options: validationOptions,
propertyName: propertyKey,
target: target.constructor,
validator: exports.MustMatchOneOfSchemasConstraint,
});
};
}
exports.MustMatchOneOfSchemasValidator = MustMatchOneOfSchemasValidator;
//# sourceMappingURL=must-match-one-of-schemas.validator.js.map