imbrn/v8n

[Question] How to validate value of property against another property?

celluj34 opened this issue · 4 comments

Hello;

How should I accomplish validating, for example, that one value is after another? In the case where I have two dates, I want to verify that an "end date" is after a "start date".

imbrn commented

Hey @celluj34 ,

Can you share an example of your scenario, please?

For custom rules, you can take a look at the documentation section: https://imbrn.dev/v8n/Extending.html

Sure thing, something like the below:

class User {
  id: string;
  name: string;
  canLoginAfter: Date;
  canLoginUntil: Date;
}

const user: User = {
  id: "<some guid value>",
  name: "celluj34",
  canLoginAfter: new Date("2022-01-01"),
  canLoginUntil: new Date("2021-01-01") //see these dates are in backwards order
}

const result = v8n()
  .schema({
      canLoginUntil: v8n().greaterThan( /* ??? */ ) // should compare to user.canLoginAfter
  })
  .test(user) //expected: false
imbrn commented

@celluj34 , thank you for sharing your code. :)

tldr; Sorry, but today v8n doesn't have validation based on any kind of context data (like an object being validated by schema rule). But having that feature seems really exciting to me.

We could design something like this:

const myCustomRule = (ruleConfig) = (value, context) => context.prop == ruleConfig.expectedProp && value;

But to achieve that, we'd have to change how validation rules are executed today. But that's really exciting.

I'll make sure to keep this thread linked with a future proposal of this feature so that you can follow it along.

Okay, thanks for the info! Yeah I was hoping to do something similar to FluentValidation from C#, I suppose I could create a new v8n().schema per object under test, but that seems a bit wasteful if you're creating a lot of them:

const genericUserValidator = (user) => v8n()
  .schema({
    canLoginUntil: v8n().greaterThan(user.canLoginAfter.valueOf())
  });

const userValidator = genericUserValidator(user);

const result = userValidator.test(user) //expected: false