UNPKG

@elsikora/nestjs-crud-automator

Version:

A library for automating the creation of CRUD operations in NestJS.

160 lines (157 loc) 7.61 kB
import { __decorate } from '../external/tslib/tslib.es6.js'; import { EMastMatchOneOfSchemasValidationErrorType } from '../enum/validator/must-match-one-of-schemas-error-type.enum.js'; import { ErrorException } from '../utility/error/exception.utility.js'; import { ValidatorConstraint, registerDecorator } from 'class-validator'; // eslint-disable-next-line @elsikora/typescript/naming-convention let MustMatchOneOfSchemasConstraint = class MustMatchOneOfSchemasConstraint { allowedValues = []; discriminatorField = null; discriminatorValue = null; errorType = 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 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 EMastMatchOneOfSchemasValidationErrorType.MISSING_DISCRIMINATOR: { return `${propertyName} is missing required discriminator field '${String(this.discriminatorField)}'`; } case EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH: { const schemasList = this.allowedValues .map((value) => { return `'${value}'`; }) .join(", "); return `${propertyName} must match one of the schemas: ${schemasList}`; } case 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 = EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH; this.prepareAllowedSchemas(_arguments); return false; } const valueAsRecord = value; if (Object.keys(valueAsRecord).length === 0) { this.errorType = EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH; this.prepareAllowedSchemas(_arguments); return false; } const constraints = _arguments.constraints; if (!constraints?.[0]?.discriminator) { this.errorType = EMastMatchOneOfSchemasValidationErrorType.UNKNOWN; return false; } try { const discriminator = constraints[0].discriminator; if (!discriminator.propertyName || typeof discriminator.propertyName !== "string") { this.errorType = EMastMatchOneOfSchemasValidationErrorType.UNKNOWN; return false; } this.discriminatorField = discriminator.propertyName; if (!(discriminator.propertyName in valueAsRecord)) { this.errorType = EMastMatchOneOfSchemasValidationErrorType.MISSING_DISCRIMINATOR; return false; } const discriminatorValue = valueAsRecord[discriminator.propertyName]; if (typeof discriminatorValue !== "string" || discriminatorValue === "") { this.errorType = EMastMatchOneOfSchemasValidationErrorType.INVALID_DISCRIMINATOR; this.discriminatorValue = String(discriminatorValue); this.prepareAllowedSchemas(_arguments); return false; } this.discriminatorValue = discriminatorValue; if (!discriminator.mapping || typeof discriminator.mapping !== "object") { this.errorType = EMastMatchOneOfSchemasValidationErrorType.SCHEMA_MISMATCH; this.prepareAllowedSchemas(_arguments); return false; } this.prepareAllowedSchemas(_arguments); if (!this.allowedValues.includes(discriminatorValue)) { this.errorType = EMastMatchOneOfSchemasValidationErrorType.INVALID_DISCRIMINATOR; return false; } return true; } catch { this.errorType = 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); } }; MustMatchOneOfSchemasConstraint = __decorate([ ValidatorConstraint({ async: false, name: "must-match-one-of-schemas" }) ], 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 ErrorException("MatchesOneOfSchemas decorator can only be applied to string properties"); } if (!discriminatorConfig?.discriminator) { throw ErrorException("discriminatorConfig must contain a discriminator property"); } const discriminator = discriminatorConfig.discriminator; if (!discriminator.propertyName || !discriminator.mapping) { throw ErrorException("discriminator must contain propertyName and mapping properties"); } registerDecorator({ constraints: [discriminatorConfig], name: "must-match-one-of-schemas", options: validationOptions, propertyName: propertyKey, target: target.constructor, validator: MustMatchOneOfSchemasConstraint, }); }; } export { MustMatchOneOfSchemasConstraint, MustMatchOneOfSchemasValidator }; //# sourceMappingURL=must-match-one-of-schemas.validator.js.map