Reputation: 95
I have issues extending joi class with custom operators. I want to validate mongodb Ids, but the extended object throws following error:
error: uncaughtException: JoiObj.string(...).objectId is not a function
TypeError: JoiObj.string(...).objectId is not a function
Code is following:
import Joi from 'joi';
import * as mongodb from 'mongodb';
interface ExtendedStringSchema extends Joi.StringSchema {
objectId(): this;
}
interface ExtendedJoi extends Joi.Root {
string(): ExtendedStringSchema;
}
const JoiObj: ExtendedJoi = Joi.extend({
base: Joi.string(),
type: 'objectId',
messages: {
'objectId.invalid': '"{{#label}}" must be a valid mongo id'
},
validate(value, helpers) {
if (!mongodb.ObjectId.isValid(value)) {
return helpers.error('objectId.invalid');
}
return value;
}
});
const objIdSchema = JoiObj.object({
id: JoiObj.string().objectId()
});
I found 2 examples:
https://github.com/sideway/joi/issues/2357
How to extend a module from npm using TypeScript?
however they use different properties than what is described in TS definition file and thus does not work.
Upvotes: 2
Views: 2043
Reputation: 124
I also had this problem. I solved it with this package.
https://www.npmjs.com/package/joi-oid
const Joi = require('joi-oid')
const schema = Joi.object({
id: Joi.objectId(),
name: Joi.string(),
age: Joi.number().min(18),
})
Good luck :)
Upvotes: 0
Reputation: 2813
You want to extend the Joi.string()
base. Keep in mind, that you can't validate new mongodb.ObjectID()
because it is of type object
. You extended Joi.string()
and this checks first if your value is of type string
. And it will stop validating if it isn't. You can only validate new mongodb.ObjectID().toHexString()
which looks like: "5f91a1449b13e3010c5548a2"
.
This answers is using joi
17.2.1 and mongodb
3.6.2
import Joi from 'joi';
import * as mongodb from 'mongodb';
interface ExtendedStringSchema extends Joi.StringSchema {
objectId(): this;
}
interface ExtendedJoi extends Joi.Root {
string(): ExtendedStringSchema;
}
const stringObjectExtension: Joi.Extension = {
type: 'string',
base: Joi.string(),
messages: {
'string.objectId': '{{#label}} must be a valid mongo id'
},
rules: {
objectId: {
validate: (value: any, helpers) => {
if (!mongodb.ObjectId.isValid(value)) {
return helpers.error('string.objectId')
}
return value;
}
}
}
};
// create extended Joi
const JoiObj: ExtendedJoi = Joi.extend(stringObjectExtension);
// create new mongodb id
const id = new mongodb.ObjectID();
const objIdSchema = JoiObj.object({
id: JoiObj.string().objectId()
});
// will fail because it won't pass the Joi.string() validation
const data1 = {
id: id
};
console.log(objIdSchema.validate(data1).error);
// will succeed
const data2 = {
id: id.toHexString()
};
console.log(objIdSchema.validate(data2).error);
Upvotes: 2