Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Argument parsing issue on different functions. #70

Closed
ozziest opened this issue Feb 3, 2025 · 5 comments
Closed

Argument parsing issue on different functions. #70

ozziest opened this issue Feb 3, 2025 · 5 comments
Assignees
Labels
bug Something isn't working v2 The next major release ideas

Comments

@ozziest
Copy link
Member

ozziest commented Feb 3, 2025

Story

This issue is related with this PR: #67

The problem is, some rules functions expect parameters one by one, but others expect an array. For example;

// isBetween.ts
export default (value: any, min: any, max: any, extra?: IContext): boolean => {
// isIn.ts
export default (value: any, options: any[] | string): boolean => {

That doesn't make sense. Parsing parameters can't cover both scenarios.

@ozziest ozziest added the bug Something isn't working label Feb 3, 2025
@ozziest ozziest self-assigned this Feb 3, 2025
@christoph-kluge
Copy link

christoph-kluge commented Feb 3, 2025

@ozziest I initially removed the spread on validate.ts and discovered the same thing. Some other tests failed, which lead me to the fact that that not all validation rules follow the same callback structure.

#67 would fix it in 2.x without introducing a breaking change. At least I didn't found a way how I could differentiate between in:1,2 and between:1,2 without adding a hard-coded check for list-like options:

        const isRuleValid = await rule.callback(
          check.value,
-          ...[...rule.params, context]
+          ['in', 'notIn', 'anotherRule'].includes(rule.name) 
+            ? [...rule.params, context] 
+            : { ...[...rule.params, context] }
        );

Sidenote: This wouldn't solve callback-syntax with custom-registered functions, unless you add another option to the register-function registering the rule-name into the ['in', 'notIn', 'anotherRule'] list.

ozziest added a commit that referenced this issue Feb 3, 2025
@ozziest ozziest mentioned this issue Feb 3, 2025
@ozziest
Copy link
Member Author

ozziest commented Feb 3, 2025

@christoph-kluge great feedback.

I've implemented a solution like this: https://github.com/axe-api/validator/pull/71/files

Basically, every rule function should have the following parameter structure:

export default (value: any, p1: any, p2: any, extra?: IContext): boolean => {
}

The first parameter should be the value that will be tested. The last parameter might be (doesn't have to be) IContext value if you need to use it.

The other parameters between the value and the extra is the parameter we send by using ,. (For example: in:1,2,3,4).
Doing this allows us to meet all the rule structures, including custom rules.

I'm open to suggestions. ☺

@ozziest ozziest changed the title Argument parsin issue on different functions. Argument parsing issue on different functions. Feb 3, 2025
@ozziest ozziest mentioned this issue Feb 3, 2025
@christoph-kluge
Copy link

christoph-kluge commented Feb 3, 2025

For v2 either #67 or #71 would be totally fine. At least #71 would cover the context, which was missing in #67 👍

For v3 I'd personally prefer a clean common-callback interface. As an example:

// isBetween.ts
export default (value: any, options: any, extra: IContext): boolean => {
    const [min, max] = ...options
    
    return value >= min && value <= max  // simplified example
}

// isIn.ts
export default (value: any, options: any, extra: IContext): boolean => {
    return options.includes(value) // simplified example
}

Which would change the callback to

const isRuleValid = await rule.callback(
    check.value,
    rule.params,
    context
);

This way each rule could decide on it's own how they interpret the given options. Context would be always given and doesn't require any additional parsing, because it's anyway the last parameter.

@christoph-kluge
Copy link

christoph-kluge commented Feb 3, 2025

Another idea could be simple rule-helper function for v2? Giving custom rules an easy way to utilize it?

// isIn.tsx
export default (value: any, ...args: any[]): boolean => {
    const {options, context} = parse(args)

    return options.includes(value)
}

What do you think?

@ozziest
Copy link
Member Author

ozziest commented Feb 3, 2025

@christoph-kluge , both ideas are great. Thanks for the contribution. ☺

I've checked all the current rules: https://validator.axe-api.com/rules.html

Usually, there are only one or two parameters in the rules. The exceptions are in and notIn. I agree with you about providing a better function structure. The following example comes my mind;

export default (value: any, params: any[], context: IContext): boolean => {
  // check
}

It's similar to your suggestions. ☺ We can push every parameter we can parse to the params. However, the solutions we discussed will require major version changes, and I'm not eager to release major changes frequently. But I'll tag this ticket to remember your suggestion for the major changes. ☺

@ozziest ozziest added the v2 The next major release ideas label Feb 3, 2025
ozziest added a commit that referenced this issue Feb 3, 2025
@ozziest ozziest closed this as completed in 02114dc Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working v2 The next major release ideas
Projects
None yet
Development

No branches or pull requests

2 participants