Ad

How To Compare The Custom Validation Type With Itself In Joi?

- 1 answer

I need to validate the object with Joi that has two keys, start and end, which are date strings in YYYY-MM-DD formats.

The validation rules I need for this object is:

  • each field is optional
  • if provided, each field should a valid date (see isValidDate)
  • end should be the date after the start (if both end and start are provided)

Joi doesn't provide the custom validations for date comparison without time, so I needed to extend it, here is my solution:

const date = Joi.extend({
    base: Joi.string(),
    name: 'string',
    language: {
        isValidDate: 'is not a valid date'
    },
    rules: [{
        name: 'isValidDate',
        validate(params, value, state, options) {
            if (!moment(value, 'YYYY-MM-DD', true).isValid()) {
                return this.createError('date.isValidDate', { v: value }, state, options);
            }

            return value;
        }
    }, {
        name: 'isDateAfter',
        params: {
            another: Joi.string().required() // This is where I'm stuck
        },
        validate(params, value, state, options) {
            if (!moment(value, 'YYYY-MM-DD', true).isAfter(params.another, 'day')) {
                return this.createError('date.isValidDate', { v: value }, state, options);
            }

            return value;
        }
    }]
});

My schema is described like that:

Joi.object({
    start: datetime.string().isValidDate(),
    end: datetime.string().isValidDate()
        .isDateAfter(Joi.ref('start', { default: '0000-00-00' }))
}).optional()

If I run this, I'll get an error:

ValidationError: {
  "another" [1]: "[ref:start]"
}

[1] "another" must be a string

103 |                     start: datetime.string().isValidDate(),
104 |                     end: datetime.string().isValidDate()
> 105 |                         .isDateAfter(Joi.ref('start', { default: '0000-00-00' }))
106 |                 }).optional()

How can I compare the 'end' key with the 'start' key if they are the same type?

Ad

Answer

Answering my own question:

I've found that there's an extension to compare date, from the maintainers of Joi itself, called joi-date-extensions. So I can easily compare dates without custom validations, like that:

date: Joi.object({
    start: Joi.date().format('YYYY-MM-DD'),
    end: Joi.date().format('YYYY-MM-DD').min(Joi.ref('start', { default: '0000-00-00' }))
}).optional()
Ad
source: stackoverflow.com
Ad