Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
481 views
in Technique[技术] by (71.8m points)

javascript - How do I add custom validators in JOI 17?

I'm on JOI 14 and can't seem to find upgrade guides to move towards 17. I see people posting similar questions for JOI 16, but the last update was 3 months ago. It doesn't look like type was required back in 16 based on what I see in How to add custom validator function in Joi?.

I am looking at https://joi.dev/api/?v=17.3.0#extensions and the description of type is The type of schema. Can be a string, or a regular expression that matches multiple types..

I tried something like this:

    const snakeAlpha = joi => {
      return {
        type: 'object',
        name: 'snakeAlpha',
        base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
      };
    };
    
    const customJoi = Joi.extend({
      type: 'object',
      rules: {
        snakeAlpha
      }
    });

It gives me this error:

    ValidationError: {
      "type": "object",
      "rules": {
        "snakeAlpha" [1]: "[joi => {
  return {
    type: 'object',
    name: 'snakeAlpha',
    base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
  };
}]"
      }
    }
    
    [1] "rules.snakeAlpha" must be of type object

I am confused since said object. I also tried string since that's what the base is, but it had same error message.

Update I also realize the original example only covered one simple rule that isn't referencing joi (regex). I also have validators that reference other custom ones lke the below. Bonus points to solve this case too.

const arrayKebabAlpha = joi => {
  return {
    type: 'string',
    name: 'arrayKebabAlpha',
    base: joi.array().items(joi.kebabAlpha())
  };
};
question from:https://stackoverflow.com/questions/66054067/how-do-i-add-custom-validators-in-joi-17

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The documentation for Joi extensions is disappointingly lacklustre for such a useful feature. Fortunately a lot of Joi's core is written using extensions so a lot can be learned from looking at the source.

If I were to write your rule as an extension it'd be like this:

const customJoi = Joi.extend(joi => ({
    type: 'string',
    base: joi.string(),
    messages: {
        'string.snakeAlpha': '{{#label}} must be snake case'
    },
    rules: {
        snakeAlpha: {
            validate(value, helpers)
            {
                if (!/^[a-z]+(_[a-z]+)*$/.test(value))
                {
                    return helpers.error('string.snakeAlpha', { value });
                }

                return value;
            }
        }
    }
}));

Which can be used like:

customJoi.object().keys({
    foo: customJoi.string().snakeAlpha()
});

UPDATE

Whether this is the correct way of working with dependant extensions, I'm not sure, but this is how I typically handle them...

I first define my extensions in an array ensuring dependant extensions are defined first. Then I'll iterate through the array re-using the previous customJoi instance so the next extension includes those defined before it. A simple working example will probably explain better than I can put into words!

(I've also simplified the extensions to be more inline with how you're used to using them)

const Joi = require('joi');

let customJoi = Joi;

const extensions = [
    joi => ({
        type: 'snakeAlpha',
        base: joi.string().regex(/^[a-z]+(_[a-z]+)*$/)
    }),
    // this instance of 'joi' will include 'snakeAlpha'
    joi => ({
        type: 'kebabAlpha',
        base: joi.string().regex(/^[a-z]+(-[a-z]+)*$/)
    }),
    // this instance of 'joi' will include 'snakeAlpha' and 'kebabAlpha'
    joi => ({
        type: 'arrayKebabAlpha',
        base: joi.array().items(joi.kebabAlpha())
    })
];

extensions.forEach(extension =>
    customJoi = customJoi.extend(extension));

customJoi.assert([ 'hello-world' ], customJoi.arrayKebabAlpha());

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...