Function wrapPropertyDecoratorUsingValidateBy

Wrap a PropertyDecorator factory function, that uses ValidateBy, like the class-validator ones, and convert it to Validator Function so it can be used in ValidZen. A Validator Function can be:

  • a simple user function that returns boolean, given the value to validate

  • OR it can throw class-validator ValidationError[] (this is how class-validator works!). This provides all the info we need to write good user explanations, get metrics etc.

Note: You NEED to have ValidateByAsValidatorFunction to have replaced ValidateBy in class-validator, to be able to convert a PropertyDecorator to a full fledged Validator Function!

Random thoughts / context

How do we replace ValidateBy with "ValidateByAsValidatorFunction" (and similarly if needed for registerDecorator)?

Solution 1 - FAIL

hijacking the class-validator code, ValidateBy() function, at runtime. Not easy, if original already loaded and used internally! For now, we are getting

import * as classValidator from 'class-validator' classValidator.ValidateBy = ValidateByAsValidatorFunction =>> TypeError: Cannot set property ValidateBy of [object Object] which has only a getter

Object.defineProperty(classValidator, "ValidateBy", { value: ValidateByAsValidatorFunction, }) => TypeError: Cannot redefine property: ValidateBy at Function.defineProperty ()

Solution 2 - WORKING!

We patch-package the library class-validator, to replace ValidateBy with ValidateByAsValidatorFunction? Temporary solution, until we find a better one or the class-validator team decides to provide this functionality somehow!

@todo(7 2 3): assumes 2 args, cater for diff arity of propertyDecoratorProducingFunction! For PropertyDecorators that use ValidateBy, the ValidationOptions object:

  • is optional
  • always the last argument, if it exists
  • can also be the first (eg no other args for @IsDefined())!
  • Type Parameters

    Parameters

    • propertyDecoratorProducingFunction: T
    • __namedParameters: {
          validationOptionsIndex: number;
      } = {}

      We need the hijack the options: ValidationOptions passed to the Decorator, to make it a ValidationOptionsWrapped.

      Usually the 2nd argument is ValidationOptions, but it can be in a different position.

      Its assumed it's always the last argument in the decorator.

      For cases of variadic Decorators (like OrAnd) we pass Infinity, since we don't know how many args precede the options. The last plainObject will be used as options, or if none exists, an options will be added as last arg.

      • validationOptionsIndex: number

    Returns T