1
votes

I've looked through Joi APIs but there's no such thing as array order. I also looked into Joi refs but currently it's impossible (correct me if I'm wrong) to use them inside arrays.

I'm thinking of using extend but not sure it's possible to retrieve the whole array.

Input:

const asc = [1,2,3];
const noOrder = [10,7,8];
const desc = [6,5,4];

Desired output:

Joi.validate(asc, Joi.array().asc()) // True
Joi.validate(asc, Joi.array().desc()) // False
Joi.validate(desc, Joi.array().desc()) // False
Joi.validate(noOrder, Joi.array().desc()) // False
Joi.validate(noOrder, Joi.array().asc()) // True

So my question is, how do I get started with this? Any idea is greatly appreciated

2
Did you tried array.ordered - Code Maniac
@CodeManiac the problem is the length of the array is variable - Brian Le
i guess you can extend something similar to how array.unique works value and a function - Code Maniac
@CodeManiac perhaps something like Joi.array().unique((a,b) => a <= b) ? - Brian Le

2 Answers

1
votes

Joi doesn't offer any built-in way to validate the order of an array so you will have to extend with your own extension, like so:

const Joi = require('joi');

const customJoi = Joi.extend((joi) => ({
  base: joi.array(),
  name: 'array',
  language: {
      asc: 'needs to be sorted in ascending order',
      desc: 'needs to be sorted in descending order'
  },

  rules: [
      {
          name: 'asc',        
          validate(params, value, state, options) { 
            const isAscOrder = value.every((x, i) => i === 0 || x >= value[i - 1]);
            return isAscOrder ? value : this.createError('array.asc', {v: value}, state, options);             
          }
      },
      {
          name: 'desc',          
          validate(params, value, state, options) {
            const isDescOrder = value.every((x, i) => i === 0 || x <= value[i - 1]);
            return isDescOrder ? value : this.createError('array.desc', {v: value}, state, options);             
          }
      }
  ]
}));

const ascSchema = customJoi.array().asc();
const descSchema = customJoi.array().desc();

// Validation results.
console.log(Joi.validate([5, 7, 9, 10], ascSchema)); //true
console.log('\n\n');
console.log(Joi.validate([5, 7, 6, 10], ascSchema)); //false
console.log('\n\n');
console.log(Joi.validate([5, 4, 2, 0], descSchema)); //true
console.log('\n\n');
console.log(Joi.validate([5, 4, 2, 6], descSchema)); //false
0
votes

As of v16.0.0, Joi supports validating the order of an array with the following schema:

Joi.array()
    .items(Joi.number())
    .sort({ order: 'ascending' });